diff --git a/CMakeLists.txt b/CMakeLists.txt index 76873776f..01ca71250 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,12 +59,15 @@ if(CORRADE_TARGET_UNIX OR CORRADE_TARGET_NACL OR CORRADE_TARGET_WINDOWS) option(WITH_MAGNUMINFO "Build magnum-info utility" OFF) endif() -# Utilities (currently only using GLX, CGL or WGL) +# Desktop-only utilities if(CORRADE_TARGET_UNIX OR CORRADE_TARGET_WINDOWS) cmake_dependent_option(WITH_FONTCONVERTER "Build magnum-fontconverter utility" OFF "NOT TARGET_GLES" OFF) cmake_dependent_option(WITH_DISTANCEFIELDCONVERTER "Build magnum-distancefieldconverter utility" OFF "NOT TARGET_GLES" OFF) endif() +# API-independent utilities +option(WITH_IMAGECONVERTER "Build magnum-imageconverter utility" OFF) + # Plugins option(WITH_WAVAUDIOIMPORTER "Build WavAudioImporter plugin" OFF) option(WITH_MAGNUMFONT "Build MagnumFont plugin" OFF) @@ -84,6 +87,9 @@ cmake_dependent_option(WITH_SHADERS "Build Shaders library" ON "NOT WITH_DEBUGTO cmake_dependent_option(WITH_TEXT "Build Text library" ON "NOT WITH_MAGNUMFONT;NOT WITH_MAGNUMFONTCONVERTER" ON) cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT;NOT WITH_DISTANCEFIELDCONVERTER" ON) +# Magnum AL Info +cmake_dependent_option(WITH_AL_INFO "Build magnum-al-info utility" OFF "WITH_AUDIO" OFF) + # EGL context and windowless EGL application, available everywhere except on # platforms which don't support extension loading if(NOT CORRADE_TARGET_EMSCRIPTEN AND NOT CORRADE_TARGET_NACL) @@ -118,7 +124,7 @@ elseif(CORRADE_TARGET_UNIX) # Windows-specific application libraries elseif(CORRADE_TARGET_WINDOWS) - if(NOT TARGET_GLES) + if(NOT TARGET_GLES OR TARGET_DESKTOP_GLES) cmake_dependent_option(WITH_WINDOWLESSWGLAPPLICATION "Build WindowlessWglApplication library" OFF "NOT WITH_MAGNUMINFO;NOT WITH_FONTCONVERTER;NOT WITH_DISTANCEFIELDCONVERTER" ON) option(WITH_WGLCONTEXT "Build WglContext library" OFF) else() @@ -138,23 +144,23 @@ if(BUILD_DEPRECATED) set(MAGNUM_BUILD_DEPRECATED 1) endif() +option(BUILD_MULTITHREADED "Build in a way that makes it possible to use multiple thread-local Magnum contexts" ON) +if(BUILD_MULTITHREADED) + set(MAGNUM_BUILD_MULTITHREADED 1) +endif() + option(BUILD_STATIC "Build static libraries (default are shared)" OFF) option(BUILD_STATIC_PIC "Build static libraries and plugins with position-independent code" ON) option(BUILD_PLUGINS_STATIC "Build static plugins (default are dynamic)" OFF) option(BUILD_TESTS "Build unit tests" OFF) cmake_dependent_option(BUILD_GL_TESTS "Build unit tests for OpenGL code" OFF "BUILD_TESTS" OFF) +cmake_dependent_option(BUILD_AL_TESTS "Build unit tests for OpenAL code" ON "BUILD_TESTS;WITH_AUDIO" OFF) if(BUILD_TESTS) find_package(Corrade REQUIRED TestSuite) - enable_testing() -endif() - -# Check compiler compatibility -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0") - message(FATAL_ERROR "Compatibility branch of Magnum is needed for use with GCC < 4.7. See the documentation for more information.") -elseif(MSVC) - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0") - message(FATAL_ERROR "Compatibility branch of Magnum is needed for use with MSVC < 2015. See the documentation for more information.") + if(CORRADE_TARGET_IOS) + set(CORRADE_TESTSUITE_BUNDLE_IDENTIFIER_PREFIX "cz.mosra.magnum") endif() + enable_testing() endif() # If targeting NaCl, set explicit OpenGL ES 2.0 support. For Android and @@ -204,6 +210,10 @@ if(TARGET_HEADLESS) set(MAGNUM_TARGET_HEADLESS 1) endif() +if(CORRADE_TARGET_EMSCRIPTEN) + include(UseEmscripten) +endif() + if(BUILD_GL_TESTS) if(MAGNUM_TARGET_HEADLESS) set(WITH_WINDOWLESSEGLAPPLICATION ON) @@ -214,9 +224,14 @@ if(BUILD_GL_TESTS) elseif(CORRADE_TARGET_APPLE) set(WITH_WINDOWLESSCGLAPPLICATION ON) set(GL_TEST_LIBRARIES Magnum MagnumWindowlessCglApplication) - elseif(CORRADE_TARGET_UNIX AND (NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES)) - set(WITH_WINDOWLESSGLXAPPLICATION ON) - set(GL_TEST_LIBRARIES Magnum MagnumWindowlessGlxApplication) + elseif(CORRADE_TARGET_UNIX) + if(MAGNUM_TARGET_GLES AND NOT MAGNUM_TARGET_DESKTOP_GLES) + set(WITH_WINDOWLESSEGLAPPLICATION ON) + set(GL_TEST_LIBRARIES Magnum MagnumWindowlessEglApplication) + else() + set(WITH_WINDOWLESSGLXAPPLICATION ON) + set(GL_TEST_LIBRARIES Magnum MagnumWindowlessGlxApplication) + endif() elseif(CORRADE_TARGET_WINDOWS) if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) set(WITH_WINDOWLESSWGLAPPLICATION ON) @@ -247,27 +262,57 @@ set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/MagnumEx set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/MagnumPlugins) # Separate install dirs for debug and release plugins -set(MAGNUM_PLUGINS_DEBUG_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d) -set(MAGNUM_PLUGINS_RELEASE_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) - -# Plugin installation dirs based on wheter we are in debug or release build, -# needed by some command-line tools +set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d) +set(MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d) +set(MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum) +set(MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) + +set(MAGNUM_PLUGINS_FONT_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMPORTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/audioimporters) + +# Plugin dirs based on wheter we are in debug or release build, needed by some +# command-line tools +if(CORRADE_TARGET_WINDOWS) + set(MAGNUM_PLUGINS_DEBUG_DIR_INIT ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}) + set(MAGNUM_PLUGINS_RELEASE_DIR_INIT ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}) +else() + set(MAGNUM_PLUGINS_DEBUG_DIR_INIT ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}) + set(MAGNUM_PLUGINS_RELEASE_DIR_INIT ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}) +endif() if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(MAGNUM_PLUGINS_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}) + set(MAGNUM_PLUGINS_DIR_INIT ${MAGNUM_PLUGINS_DEBUG_DIR_INIT}) else() - set(MAGNUM_PLUGINS_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}) + set(MAGNUM_PLUGINS_DIR_INIT ${MAGNUM_PLUGINS_RELEASE_DIR_INIT}) endif() -set(MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fonts) -set(MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fonts) -set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fontconverters) -set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fontconverters) -set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/imageconverters) -set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/imageconverters) -set(MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/importers) -set(MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/importers) -set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/audioimporters) -set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/audioimporters) +# Make these paths configurable from outside. This is *not* PATH, because CMake +# always converts the path to an absolute location internally, making it +# impossible to specify relative paths there. Sorry in advance for not having +# the dir selection button in CMake GUI. +set(MAGNUM_PLUGINS_DEBUG_DIR ${MAGNUM_PLUGINS_DEBUG_DIR_INIT} + CACHE STRING "Base directory where to look for Magnum plugins for debug builds") +set(MAGNUM_PLUGINS_RELEASE_DIR ${MAGNUM_PLUGINS_RELEASE_DIR_INIT} + CACHE STRING "Base directory where to look for Magnum plugins for release builds") +set(MAGNUM_PLUGINS_DIR ${MAGNUM_PLUGINS_DIR_INIT} + CACHE STRING "Base directory where to look for Magnum plugins") add_subdirectory(modules) add_subdirectory(src) diff --git a/CREDITS.md b/CREDITS.md index 4cf4d5fb1..19cc2f7a4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -35,5 +35,10 @@ Contributors to Magnum library enhancements, GlfwApplication implementation, bug reports, documentation improvements * Gerhard de Clercq -- Windows RT (Store/Phone) port +* Ashwin Ravichandran ([@](ashrko619)[https://github.com/ashrko619]) -- + Bézier curve implementation +* Alice Margatroid ([@Alicemargatroid](https://github.com/Alicemargatroid)) -- + Multi-channel support in Audio library, standard conformance, float, + double, A-Law and μ-Law format support in `WavAudioImporter` plugin Big thanks to everyone involved! diff --git a/README.md b/README.md index a65735174..4d9c4c22b 100644 --- a/README.md +++ b/README.md @@ -53,15 +53,15 @@ Graphics APIs: Platforms: * **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through - SDL2 or GLUT toolkit) [![Build Status](https://travis-ci.org/mosra/magnum.svg?branch=master)](https://travis-ci.org/mosra/magnum) -* **Windows** natively or using ANGLE (through SDL2 or GLUT toolkit) [![Build status](https://ci.appveyor.com/api/projects/status/5b477m034cfaskse/branch/master?svg=true)](https://ci.appveyor.com/project/mosra/magnum/branch/master) -* **OS X** (through SDL2 toolkit) [![Build Status](https://travis-ci.org/mosra/magnum.svg?branch=master)](https://travis-ci.org/mosra/magnum) -* **iOS** (through SDL2 toolkit) -* **Android** 2.3 (API Level 9) and higher -* **Windows RT** (Store/Phone) using ANGLE (through SDL2 toolkit) + SDL2, GLFW or GLUT toolkit) [![Build Status](https://travis-ci.org/mosra/magnum.svg?branch=master)](https://travis-ci.org/mosra/magnum) [![Coverage Status](https://coveralls.io/repos/github/mosra/magnum/badge.svg?branch=master)](https://coveralls.io/github/mosra/magnum?branch=master) +* **Windows** on both MSVC and MinGW, natively or using ANGLE (through SDL2, GLFW or GLUT toolkit) [![Build Status](https://ci.appveyor.com/api/projects/status/5b477m034cfaskse/branch/master?svg=true)](https://ci.appveyor.com/project/mosra/magnum/branch/master) +* **OS X** (through SDL2 or GLFW toolkit) [![Build Status](https://travis-ci.org/mosra/magnum.svg?branch=master)](https://travis-ci.org/mosra/magnum) +* **iOS** (through SDL2 toolkit) [![Build Status](https://travis-ci.org/mosra/magnum.svg?branch=master)](https://travis-ci.org/mosra/magnum) +* **Android** 2.3 (API Level 9) and higher [![Build Status](https://travis-ci.org/mosra/magnum.svg?branch=master)](https://travis-ci.org/mosra/magnum) +* **Windows RT** (Store/Phone) using ANGLE (through SDL2 toolkit) [![Build Status](https://ci.appveyor.com/api/projects/status/5b477m034cfaskse/branch/master?svg=true)](https://ci.appveyor.com/project/mosra/magnum/branch/master) * **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), both `newlib` and `glibc` toolchains are supported) -* **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) +* **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) [![Build Status](https://travis-ci.org/mosra/magnum.svg?branch=master)](https://travis-ci.org/mosra/magnum) FEATURES ======== @@ -89,11 +89,9 @@ comprehensive guide for building, packaging and crosscompiling. Minimal dependencies -------------------- -- C++ compiler with good C++11 support. Compilers which are tested to have - everything needed are **GCC** >= 4.7, **Clang** >= 3.1 and **MSVC** 2015. - On Windows you can also use **MinGW-w64**. GCC 4.6, 4.5, 4.4 and MSVC 2013 - support involves some ugly workarounds and thus is available only in - `compatibility` branch. +* C++ compiler with good C++11 support. Compilers which are tested to have + everything needed are **GCC** >= 4.7, **Clang** >= 3.1 and **MSVC** >= 2015. + On Windows you can also use **MinGW-w64**. * **CMake** >= 2.8.12 * **Corrade** - Plugin management and utility library. You can get it at https://github.com/mosra/corrade. diff --git a/doc/building.dox b/doc/building.dox index fc853a21e..90beea486 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -33,10 +33,8 @@ namespace Magnum { Minimal set of tools and libraries required for building is: - C++ compiler with good C++11 support. Compilers which are tested to have - everything needed are **GCC** >= 4.7, **Clang** >= 3.1 and **MSVC** 2015. - On Windows you can also use **MinGW-w64**. GCC 4.6, 4.5, 4.4 and MSVC 2013 - support involves some ugly workarounds and thus is available only in - `compatibility` branch. + everything needed are **GCC** >= 4.7, **Clang** >= 3.1 and **MSVC** >= 2015. + On Windows you can also use **MinGW-w64**. - **CMake** >= 2.8.12 - **Corrade** - Plugin management and utility library. See @ref building-corrade "Corrade download and installation guide" for more @@ -52,12 +50,6 @@ compressed archive or use the command line: git clone git://github.com/mosra/magnum.git -If you need to use the `compatibility` branch, check it out as following from -the cloned repository or download the particular archive from -https://github.com/mosra/magnum/tree/compatibility. - - git checkout compatibility - @section building-compilation Compilation, installation Relevant information about CMake usage was described in @@ -103,8 +95,7 @@ value to that directory (e.g. `-DCMAKE_INSTALL_PREFIX=C:/Sys`). @subsubsection building-windows-msvc Using Visual Studio -On Windows CMake by default creates Visual Studio project files. You need to -use `compatibility` branch to compile with MSVC 2013, as said above. +On Windows CMake by default creates Visual Studio project files. 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 @@ -166,13 +157,19 @@ available for desktop OpenGL only, see @ref requires-gl. - `TARGET_GLES2` -- Target OpenGL ES 2.0. Currently enabled by default when `TARGET_GLES` is set. - `TARGET_DESKTOP_GLES` -- Target OpenGL ES on desktop, i.e. use OpenGL ES - emulation in desktop OpenGL library. Might not be supported in all drivers. + emulation in desktop OpenGL library. Available on Linux and Windows, though + might not be supported by all drivers. - `TARGET_HEADLESS` -- Build command-line utilities for use on a headless machine. Basically it means that EGL with no display attachment is being used everywhere instead of platform-specific toolkits like CGL, GLX or WGL. Supported mainly on OpenGL ES drivers, for desktop OpenGL the only driver that supports this configuration is NVidia >= 355. +By default the engine is built in a way that allows having multiple +thread-local Magnum contents. This might cause some performance penalties -- if +you are sure that you will never need such feature, you can disable it via the +`BUILD_MULTITHREADED` option. + The features used can be conveniently detected in depending projects both in CMake and C++ sources, see @ref cmake and @ref Magnum/Magnum.h for more information. See also @ref corrade-cmake and @ref Corrade/Corrade.h for @@ -229,17 +226,31 @@ information): - `WITH_GLXCONTEXT` -- GLX context - `WITH_WGLCONTEXT` -- WGL context -There are also a few command-line utilities. They are currently available only -on Linux, Mac OS X and Windows, also disabled by default: +There are also a few command-line utilities, also disabled by default: - `WITH_MAGNUMINFO` - @ref magnum-info "magnum-info" executable, provides - information about the engine and OpenGL capabilities. + information about the engine and OpenGL capabilities. Depends on some + windowless application library. +- `WITH_AL_INFO` -- @ref magnum-al-info "magnum-al-info" executable, provides + information about OpenAL capabilities. - `WITH_DISTANCEFIELDCONVERTER` - @ref magnum-distancefieldconverter "magnum-distancefieldconverter" executable for converting black&white images to distance field textures. - Enables also building of TextureTools library. + Enables also building of @ref TextureTools library. Available only on + desktop GL, depends on some windowless application library. - `WITH_FONTCONVERTER` - @ref magnum-fontconverter "magnum-fontconverter" executable for converting fonts to raster ones. Enables also building of - Text library. + @ref Text library. Available only on desktop GL, depends on some windowless + application library. +- `WITH_IMAGECONVERTER` - @ref magnum-imageconverter "magnum-imageconverter" + executable for converting images of different formats. + +Some of these utilities operate with plugins and they search for them in the +default plugin locations. You can override those locations using +`MAGNUM_PLUGINS_DIR` and `MAGNUM_PLUGINS_[DEBUG|RELEASE]_DIR` variables, much +like when using Magnum from dependent projects -- see @ref cmake for more +information. In particular, if you specify them as relative paths, the path +will be taken relative to executable location, which is useful for making +relocatable installations. Magnum also contains a set of dependency-less plugins for importing essential file formats. Additional plugins are provided in separate plugin repository, @@ -277,9 +288,25 @@ in build directory. On Windows the tests require the library to be installed with DLLs accessible through `PATH`. See @ref building-windows "above Windows documentation" for more information. -Platforms which have windowless context creation implemented (currently only -desktop Linux) can build also tests for OpenGL functionality. You can enable -them with `BUILD_GL_TESTS`. +The @ref Audio library has tests which require OpenAL to be able to create a +context. That is the case on most platforms, so they are enabled by default. +In case it's not possible to have OpenAL context (such as when running +@ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" tests under Node.js), you can +disable building of them with `BUILD_AL_TESTS`. The tests are suffixed with +`ALTest` so they can be also selectively included/excluded when running CTest, +e.g.: + + ctest -E ALTest # run everything except tests requiring OpenAL context + +Platforms which have windowless GL context creation implemented (currently all +platforms except @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", +@ref CORRADE_TARGET_NACL "NaCl", @ref CORRADE_TARGET_WINDOWS_RT "Windows RT" +and @ref CORRADE_TARGET_ANDROID "Android") can build also tests for OpenGL +functionality. You can enable them with `BUILD_GL_TESTS`. All GL tests are +suffixed with `GLTest` so they can be also selectively included/excluded when +running CTest, e.g.: + + ctest -R GLTest # run only tests requiring OpenGL context @subsection building-doc Building documentation @@ -378,8 +405,9 @@ contents in `toolchains/` subdirectory. git submodule update Note that CMake for some reason treats `CMAKE_PREFIX_PATH` and -`CMAKE_INSTALL_PREFIX` differently while crosscompiling and you may need to set -also `CMAKE_FIND_ROOT_PATH` to make it able to find the dependencies. +`CMAKE_INSTALL_PREFIX` differently while crosscompiling and you may need to add +dependency paths to both `CMAKE_PREFIX_PATH` and `CMAKE_FIND_ROOT_PATH` to make +it able to find the dependencies. @subsection building-cross-winrt Crosscompiling for Windows RT @@ -390,15 +418,23 @@ installation path for WinRT dependencies is in `C:/Sys-winrt`. You need at least Windows 8.1, Visual Studio 2013 and Windows 8.1 Store/Phone SDK installed. Windows RT applications support OpenGL only through ANGLE, which is currently limited to OpenGL ES. Download and build ANGLE @ref building-windows-angle "according to instructions above", -but use project files from the `winrt/` directory instead. Upcoming version -2.0.4 of SDL has support for WinRT applications, download the source from -https://www.libsdl.org/hg.php and use project files from the `VisualC-WinRT` -directory. Because WinRT applications run in a sandbox, it's recommended to -build the library as static so you don't have to bundle all the DLLs. Example: +but use project files from the `winrt/` directory instead. Version 2.0.4 of SDL +has support for WinRT applications, download the source from +https://www.libsdl.org/download-2.0.php and use project files from the +`VisualC-WinRT` directory. Because WinRT applications run in a sandbox, it's +recommended to build the library as static so you don't have to bundle all the +DLLs. Example: mkdir build-winrt cd build-winrt - cmake -DCORRADE_RC_EXECUTABLE="C:/Sys/bin/corrade-rc.exe" -DCMAKE_INSTALL_PREFIX="C:/Sys-winrt" -DBUILD_STATIC=ON -DWITH_SDL2APPLICATION=ON -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=8.1 -G "Visual Studio 14 2015" .. + cmake .. ^ + -DCMAKE_SYSTEM_NAME=WindowsStore ^ + -DCMAKE_SYSTEM_VERSION=10 ^ + -DCORRADE_RC_EXECUTABLE="C:/Sys/bin/corrade-rc.exe" ^ + -DCMAKE_INSTALL_PREFIX="C:/Sys-winrt" ^ + -DBUILD_STATIC=ON ^ + -DWITH_SDL2APPLICATION=ON ^ + -G "Visual Studio 14 2015" .. cmake --build . Change `WindowsStore` to `WindowsPhone` if you want to build for Windows Phone @@ -455,9 +491,7 @@ to find the compiler. NaCl currently supports only OpenGL ES 2, thus `TARGET_GLES` and `TARGET_GLES2` is always enabled. Then create build directories for x86-32 and x86-64 and run cmake and build -command in them. The toolchains need access to the platform file, so be sure to -properly set **absolute** path to `modules/` directory containing -`Platform/NaCl.cmake`. Also adapt `CMAKE_INSTALL_PREFIX` to the same value as +command in them. Be sure to adapt `CMAKE_INSTALL_PREFIX` to the same value as in `NACL_PREFIX` in toolchain file and specify path where Corrade is installed in `CMAKE_PREFIX_PATH`. @@ -501,10 +535,8 @@ to path where Emscripten is installed. Default is `/usr/lib/emscripten`. Emscripten supports dynamic libraries only to simplify porting and they are generally slower, thus `BUILD_STATIC` is implicitly enabled. -Then create build directory and run cmake and build command in it. The -toolchain needs access to its platform file, so be sure to properly set **absolute** -path to `modules/` directory containing `Platform/Emscripten.cmake`. Also set -`CMAKE_INSTALL_PREFIX` to path contained in `EMSCRIPTEN_TOOLCHAIN_PATH`. +Then create build directory and run cmake and build command in it. Be sure to +set `CMAKE_INSTALL_PREFIX` to path contained in `EMSCRIPTEN_TOOLCHAIN_PATH`. WebGL 1.0 (GLES 2.0 equivalent) is enabled by default, switch to 2.0 (GLES 3.0 equivalent) by disabling `TARGET_GLES2`. @@ -536,10 +568,8 @@ building your projects for Emscripten. You will need OSX and Xcode installed. Set `CMAKE_OSX_ROOT` to SDK you want to target and enable all desired -architectures in `CMAKE_OSX_ARCHITECTURES`. The toolchain needs access to its -platform file, so be sure to properly set **absolute** path to `modules/` -directory containing `Platform/iOS.cmake`. Set `CMAKE_INSTALL_PREFIX` to prefix -where you store other iOS dependencies such as Corrade or SDL2. +architectures in `CMAKE_OSX_ARCHITECTURES`. Be sure to set `CMAKE_INSTALL_PREFIX` +to prefix where you store other iOS dependencies such as Corrade or SDL2. As every application is in its own sandbox, it doesn't make sense to build shared libraries (although it is supported). Enable `BUILD_STATIC` to build @@ -547,6 +577,10 @@ static libraries. You might also have problems using dynamic plugins, enable `BUILD_PLUGINS_STATIC` to build also plugins as static. OpenGL ES 2.0 is enabled by default, switch to 3.0 by disabling `TARGET_GLES2`. +Please note that `BUILD_MULTITHREADED` is supported only since Xcode 7.3 and +doesn't work on `i386` iOS Simulator, you need to disable it in order to build +for older platforms. + mkdir build-ios && cd build-ios cmake .. \ -DCMAKE_TOOLCHAIN_FILE=../toolchains/generic/iOS.cmake \ @@ -575,11 +609,9 @@ where NDK is installed. Default is `/opt/android-ndk`. Adapt also `ANDROID_SYSROOT` to your preferred API level. You might also need to update `ANDROID_TOOLCHAIN_PREFIX` and `ANDROID_TOOLCHAIN_ROOT` to fit your system. -Then create build directory and run cmake and 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` and specify -path where Corrade is installed in `CMAKE_PREFIX_PATH`. +Then create build directory and run cmake and build command in it. Be sure to +set `CMAKE_INSTALL_PREFIX` to `/usr` subdirectory of `ANDROID_SYSROOT` and +specify path where Corrade is installed in `CMAKE_PREFIX_PATH`. Note that `BUILD_STATIC` is implicitly enabled, because manually loading all depending shared libraries using JNI would be too inconvenient. The engine is @@ -619,13 +651,15 @@ building your projects for Android. @subsection building-ci-travis Travis -In `package/ci/` there is `travis.yml` file with Linux GCC 4.7 and OSX Clang -configuration. Online at https://travis-ci.org/mosra/magnum. +In `package/ci/` there is `travis.yml` file with Linux GCC 4.7, OSX Clang, iOS +GLES2/GLES3 and Emscripten WebGL1/WebGL2 configuration. Online at +https://travis-ci.org/mosra/magnum. The Linux build has code coverage reports +available online at https://coveralls.io/github/mosra/magnum. @subsection building-ci-appveyor AppVeyor -In `package/ci/` there is `appveyor.yml` file with Windows MSVC configuration. -Online at https://ci.appveyor.com/project/mosra/magnum. +In `package/ci/` there is `appveyor.yml` file with Windows desktop MSVC, MinGW +and Windows RT GLES2/GLES3 configuration. Online at https://ci.appveyor.com/project/mosra/magnum. @subsection building-ci-jenkins Jenkins diff --git a/doc/cmake.dox b/doc/cmake.dox index 972858b2c..9bd1fbce7 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -27,6 +27,8 @@ namespace Magnum { /** @page cmake Usage with CMake @brief Guide how to find and use Magnum with CMake build system +@tableofcontents + Magnum uses CMake build system for both building and integration into your projects. The logic is in module `FindMagnum.cmake` distributed with the engine in `modules/` directory, you are encouraged to copy it along with @@ -140,7 +142,9 @@ Lastly, a few utility executables are available: - `distancefieldconverter` -- @ref magnum-distancefieldconverter executable - `fontconverter` -- @ref magnum-fontconverter executable +- `imageconverter` -- @ref magnum-imageconverter executable - `info` -- @ref magnum-info executable +- `al-info` -- @ref magnum-al-info executable Note that [each namespace](namespaces.html), all @ref Platform libraries and each plugin class contain more detailed information about dependencies, @@ -180,6 +184,8 @@ are also available as preprocessor variables if including included - `MAGNUM_BUILD_STATIC` -- Defined if compiled as static libraries. Default are shared libraries. +- `MAGNUM_BUILD_MULTITHREADED` -- Defined if compiled in a way that allows + having multiple thread-local Magnum contexts. The default. - `MAGNUM_TARGET_GLES` -- Defined if compiled for OpenGL ES - `MAGNUM_TARGET_GLES2` -- Defined if compiled for OpenGL ES 2.0 - `MAGNUM_TARGET_GLES3` -- Defined if compiled for OpenGL ES 3.0 @@ -209,5 +215,31 @@ Corrade library provides also its own set of CMake macros and variables, see @ref cmake-plugins "Plugins repository", @ref cmake-integration "Integration repository" and @ref cmake-extras "Extras repository" have also their own CMake modules. +@section cmake-modules Other CMake modules + +The `modules/` directory contains more useful CMake modules: + +- `FindOpenAL.cmake` -- CMake module for finding OpenAL. This is a forked + version of the upstream module that works properly with + @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". Copy this to your module + directory if you want to use the @ref Audio library on Emscripten. +- `FindGLFW.cmake` -- CMake module for finding GLFW. Copy this to your module + directory if you want to use @ref Platform::GlfwApplication. +- `FindEGL.cmake` -- CMake module for finding EGL. Copy this to your + module directory if you want to target embedded platforms such as + @ref CORRADE_TARGET_IOS "iOS", @ref CORRADE_TARGET_ANDROID "Android", + @ref CORRADE_TARGET_WINDOWS_RT "Windows RT" or + @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" or if you want to use EGL + instead of GLX/WGL/CGL on a desktop platform. +- `FindOpenGLES2.cmake`, `FindOpenGLES3.cmake` -- CMake module for finding + OpenGL ES 2.0 / 3.0 library. Copy this to your module directory if you want + to target @ref MAGNUM_TARGET_GLES "OpenGL ES". +- `FindSDL2.cmake` -- CMake module for finding SDL 2. Copy this to your + module directory if you want to use @ref Platform::Sdl2Application. + +See also relevant section for @ref corrade-cmake-modules "Corrade", +@ref cmake-plugins-modules "Plugins", @ref cmake-integration-modules "Integration" +and @ref cmake-extras-modules "Extras" projects. + */ } diff --git a/doc/generated/hello.cpp b/doc/generated/hello.cpp index 807f3c280..5912b10c4 100644 --- a/doc/generated/hello.cpp +++ b/doc/generated/hello.cpp @@ -31,6 +31,7 @@ #include using namespace Magnum; +using namespace Magnum::Math::Literals; class Hello: public Platform::Application { public: @@ -42,8 +43,8 @@ private: Hello::Hello(const Arguments& arguments): Platform::Application(arguments) { Renderer::setClearColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)); - Debug() << "Hello! This application is running on" << Context::current()->version() - << "using" << Context::current()->rendererString(); + Debug() << "Hello! This application is running on" << Context::current().version() + << "using" << Context::current().rendererString(); } void Hello::drawEvent() { diff --git a/doc/generated/shaders.cpp b/doc/generated/shaders.cpp index edf4cc11f..4b2f83f11 100644 --- a/doc/generated/shaders.cpp +++ b/doc/generated/shaders.cpp @@ -67,6 +67,7 @@ #include "configure.h" using namespace Magnum; +using namespace Magnum::Math::Literals; struct ShaderVisualizer: Platform::WindowlessApplication { using Platform::WindowlessApplication::WindowlessApplication; diff --git a/doc/getting-started.dox b/doc/getting-started.dox index 57e6c2634..3989bdd09 100644 --- a/doc/getting-started.dox +++ b/doc/getting-started.dox @@ -59,20 +59,12 @@ dependencies means just cloning them into your project tree: git clone git://github.com/mosra/corrade.git git clone git://github.com/mosra/magnum.git -The `master` branch supports GCC 4.7+, Clang and MSVC 2015 compilers, for older -versions you need to use `compatibility` branches, please see -@ref building-corrade "Corrade" and @ref building "Magnum" installation guides -for detailed information. If you are using `compatibility` branch of Magnum and -Corrade, replace `modules/FindCorrade.cmake` from the bootstrap project with -[the one from compatibility branch](https://github.com/mosra/corrade/blob/compatibility/modules/FindCorrade.cmake) -so the compatibility mode gets properly detected and used. - Then open the `CMakeLists.txt` file in the root of bootstrap project and add these two new subdirectories using `add_subdirectory()` so the file looks like this: @code -cmake_minimum_required(VERSION 2.8.9) +cmake_minimum_required(VERSION 2.8.12) project(MyApplication) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/modules/") @@ -83,7 +75,7 @@ add_subdirectory(src) @endcode If you want to install Corrade and Magnum separately instead of cloning them -into your project tree, just follow the installation guides mentioned above. +into your project tree, just follow @ref building "the full installation guide". Don't forget to enable `WITH_SDL2APPLICATION` (or `WITH_GLUTAPPLICATION`, if you are using GLUT) when building Magnum so the bootstrap project can use it later. @@ -110,6 +102,12 @@ standard CMake installation, these aren't part of it and thus must be distributed with the project. These files are just verbatim copied from Magnum repository. +@note These modules are just the bare minimum you need for starting. If you + plan to use additional functionality not part of the core library or target + specific platforms, you may need to copy additional modules. See @ref cmake, + @ref cmake-plugins, @ref cmake-integration and @ref cmake-extras for more + information. + Directory `src/` contains the actual project. To keep things simple, the project consists of just one source file with the most minimal code possible: @code @@ -163,21 +161,21 @@ In the following tutorials the code will be explained more thoroughly. In Linux (and other Unix-based OSs) you can build the application along with the subprojects using the following three commands: create out-of-source build directory, run cmake, enable SDL2 application in the Magnum subproject and then -build the everything. The compiled application binary will then appear in src/ -subdirectory of build dir: +build everything. The compiled application binary will then appear in `src/` +subdirectory of the build dir: mkdir -p build && cd build cmake .. -DWITH_SDL2APPLICATION=ON cmake --build . ./src/MyApplication -On Windows you can use either MSVC or MinGW-w64 compiler. It's then up to you -whether you will use command-line, QtCreator or Visual Studio. With Visual -Studio the most straightforward way to create the project file is via the -command-line: +On Windows you can use either MSVC or MinGW-w64 compiler and prebuilt SDL2 +binaries can be downloaded at https://libsdl.org/download-2.0.php. It's then up +to you whether you will use command-line, QtCreator or Visual Studio. With +Visual Studio the most straightforward way to create the project file is via +the command-line: - mkdir build - cd build + mkdir build && cd build cmake .. -DWITH_SDL2APPLICATION=ON You can also use CMake GUI. Then open the `MyApplication.sln` project file @@ -188,11 +186,19 @@ where to create build directory, allows you to specify initial CMake parameters (e.g. the `-DWITH_SDL2APPLICATION=ON` parameter) and then you can just press *Configure* and everything is ready to be built. +If you have SDL2 in a non-standard location and CMake can't find it, you need +to specify where SDL `include/` and `lib/` directories are through +`CMAKE_PREFIX_PATH`. So, for example, on Windows, the full CMake invocation +might look like this: + + cmake .. -DCMAKE_PREFIX_PATH="C:/Users/you/Downloads/SDL2-2.0.4" -DWITH_SDL2APPLICATION=ON + On Windows you may get errors about missing DLLs when running the application. The solution is either compiling everything as static (enable `BUILD_STATIC` CMake option) or installing the dependencies somewhere. To install them, change `CMAKE_INSTALL_PREFIX` to your liking and run the `install` target. Then run -the application with `bin/` subdirectory of installation prefix as working dir. +the application with `bin/` subdirectory of installation prefix as working dir +or add the `bin/` subdirectory to `PATH`. @image html getting-started.png @image latex getting-started.png @@ -211,10 +217,12 @@ First include the needed headers: And in the constructor (which is currently empty) change the clear color and print something to debug output: @code +using namespace Magnum::Math::Literals; + Renderer::setClearColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)); -Debug() << "Hello! This application is running on" << Context::current()->version() - << "using" << Context::current()->rendererString(); +Debug() << "Hello! This application is running on" << Context::current().version() + << "using" << Context::current().rendererString(); @endcode After rebuilding and starting the application, the clear color changes to diff --git a/doc/mainpage.dox b/doc/mainpage.dox index e1af78bb3..9d9a9b9a4 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -77,9 +77,9 @@ Graphics APIs: Platforms: - **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through - SDL2 or GLUT toolkit) -- **Windows** natively or using ANGLE (through SDL2 or GLUT toolkit) -- **OS X**, **iOS** (through SDL2 toolkit) + SDL2, GLFW or GLUT toolkit) +- **Windows** using both MSVC and MinGW, natively or using ANGLE (through SDL2, GLFW or GLUT toolkit) +- **OS X**, **iOS** (through SDL2 or GLFW toolkit) - **Android** 2.3 (API Level 9) and higher - **Windows RT** (Store/Phone) using ANGLE (through SDL2 toolkit) - **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), diff --git a/doc/openal-support.dox b/doc/openal-support.dox index 06278b89a..6f9d1b58d 100644 --- a/doc/openal-support.dox +++ b/doc/openal-support.dox @@ -38,8 +38,12 @@ functions and enum values are exposed through the API. Extension | Status ------------------------------------------- | ------ +@alc_extension{ENUMERATION,EXT} | done @al_extension{EXT,double} | done @al_extension{EXT,float32} | done +@al_extension{EXT,ALAW} | done +@al_extension{EXT,MULAW} | done +@al_extension{EXT,MCFORMATS} | done @subsection openal-extension-support-soft OpenAL Soft Extensions diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 37dd149b3..cb2563022 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -52,7 +52,7 @@ OpenGL function | Matching API --------------------------------------- | ------------ @fn_gl{BeginConditionalRender}, `glEndConditionalRender()` | @ref SampleQuery::beginConditionalRender(), \n @ref SampleQuery::endConditionalRender() @fn_gl{BeginQuery}, `glEndQuery()` | @ref PrimitiveQuery::begin(), \n @ref SampleQuery::begin(), \n @ref TimeQuery::begin(), \n @ref AbstractQuery::end() -@fn_gl{BeginQueryIndexed}, `glEndQueryIndexed()` | | +@fn_gl{BeginQueryIndexed}, `glEndQueryIndexed()` | @ref PrimitiveQuery::begin(UnsignedInt), \n @ref PrimitiveQuery::end() @fn_gl{BeginTransformFeedback}, `glEndTransformFeedback()` | @ref TransformFeedback::begin(), @ref TransformFeedback::end() @fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation() @fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere @@ -101,8 +101,8 @@ OpenGL function | Matching API @fn_gl{CompressedTexSubImage1D}, \n `glCompressedTextureSubImage1D()`, \n @fn_gl_extension{CompressedTextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage2D}, \n `glCompressedTextureSubImage2D()`, \n @fn_gl_extension{CompressedTextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage3D}, \n `glCompressedTextureSubImage3D()`, \n @fn_gl_extension{CompressedTextureSubImage3D,EXT,direct_state_access} | @ref Texture::setCompressedSubImage(), \n @ref TextureArray::setCompressedSubImage(), \n @ref CubeMapTexture::setCompressedSubImage(), \n @ref CubeMapTextureArray::setCompressedSubImage(), \n @ref RectangleTexture::setCompressedSubImage() @fn_gl{CopyBufferSubData}, \n `glCopyNamedBufferSubData()`, \n @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access} | @ref Buffer::copy() @fn_gl{CopyImageSubData} | | -@fn_gl{CopyTexImage1D}, \n @fn_gl_extension{CopyTextureImage1D,EXT,direct_state_access}, \n @fn_gl{CopyTexImage2D}, \n @fn_gl_extension{CopyTextureImage2D,EXT,direct_state_access} | | -@fn_gl{CopyTexSubImage1D}, \n `glCopyTextureSubImage1D()`, \n @fn_gl_extension{CopyTextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{CopyTexSubImage2D}, \n `glCopyTextureSubImage2D()`, \n @fn_gl_extension{CopyTextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{CopyTexSubImage3D}, \n `glCopyTextureSubImage3D()`, \n @fn_gl_extension{CopyTextureSubImage3D,EXT,direct_state_access} | | +@fn_gl{CopyTexImage1D}, \n @fn_gl{CopyTexImage2D} | @ref Framebuffer::copyImage() +@fn_gl{CopyTexSubImage1D}, \n `glCopyTextureSubImage1D()`, \n @fn_gl_extension{CopyTextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{CopyTexSubImage2D}, \n `glCopyTextureSubImage2D()`, \n @fn_gl_extension{CopyTextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{CopyTexSubImage3D}, \n `glCopyTextureSubImage3D()`, \n @fn_gl_extension{CopyTextureSubImage3D,EXT,direct_state_access} | @ref Framebuffer::copySubImage() @fn_gl{CreateProgram}, @fn_gl{DeleteProgram} | @ref AbstractShaderProgram constructor and destructor @fn_gl{CreateShader}, @fn_gl{DeleteShader} | @ref Shader constructor and destructor @fn_gl{CreateShaderProgram} | | @@ -124,10 +124,10 @@ OpenGL function | Matching API @fn_gl{DispatchCompute} | @ref AbstractShaderProgram::dispatchCompute() @fn_gl_extension{DispatchComputeGroupSize,ARB,compute_variable_group_size} | | @fn_gl{DispatchComputeIndirect} | | -@fn_gl{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(), \n @ref MeshView::draw() +@fn_gl{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(AbstractShaderProgram&), \n @ref MeshView::draw(AbstractShaderProgram&) @fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | | @fn_gl{DrawBuffer}, \n `glNamedFramebufferDrawBuffer()`, \n @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, \n @fn_gl{DrawBuffers}, \n `glNamedFramebufferDrawBuffers()`, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForDraw(), \n @ref Framebuffer::mapForDraw() -@fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | | +@fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | @ref Mesh::draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt), \n @ref MeshView::draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt) @subsection opengl-mapping-functions-e E @@ -478,6 +478,7 @@ OpenGL function | Matching API @def_gl{MAX_VERTEX_ATTRIB_STRIDE} | | @def_gl{MAX_VERTEX_ATTRIB_BINDINGS} | | @def_gl{MAX_VERTEX_ATTRIB_RELATIVE_OFFSET} | | +@def_gl{MAX_VERTEX_STREAMS} | @ref TransformFeedback::maxVertexStreams() @def_gl{MAX_VIEWPORTS} | | @def_gl{MAX_VIEWPORT_DIMS} | @ref AbstractFramebuffer::maxViewportSize() @def_gl{MIN_FRAGMENT_INTERPOLATION_OFFSET}, \n @def_gl{MAX_FRAGMENT_INTERPOLATION_OFFSET} | | @@ -488,7 +489,7 @@ OpenGL function | Matching API @def_gl{NUM_EXTENSIONS} | @ref Context::supportedExtensions() @def_gl{NUM_PROGRAM_BINARY_FORMATS}, \n @def_gl{PROGRAM_BINARY_FORMATS} | | @def_gl{NUM_SHADER_BINARY_FORMATS}, \n @def_gl{SHADER_BINARY_FORMATS} | | -@def_gl{PACK_ALIGNMENT}, \n @def_gl{PACK_IMAGE_HEIGHT}, \n @def_gl{PACK_LSB_FIRST}, \n @def_gl{PACK_ROW_LENGTH}, \n @def_gl{PACK_SKIP_IMAGES}, \n @def_gl{PACK_SKIP_PIXELS}, \n @def_gl{PACK_SKIP_ROWS}, \n @def_gl{PACK_SWAP_BYTES}, \n @def_gl{UNPACK_ALIGNMENT}, \n @def_gl{UNPACK_IMAGE_HEIGHT}, \n @def_gl{UNPACK_LSB_FIRST}, \n @def_gl{UNPACK_ROW_LENGTH}, \n @def_gl{UNPACK_SKIP_IMAGES}, \n @def_gl{UNPACK_SKIP_PIXELS}, \n @def_gl{UNPACK_SKIP_ROWS}, \n @def_gl{UNPACK_SWAP_BYTES} | not queryable +@def_gl{PACK_ALIGNMENT}, \n @def_gl{PACK_IMAGE_HEIGHT}, \n @def_gl{PACK_ROW_LENGTH}, \n @def_gl{PACK_SKIP_IMAGES}, \n @def_gl{PACK_SKIP_PIXELS}, \n @def_gl{PACK_SKIP_ROWS}, \n @def_gl{PACK_SWAP_BYTES}, \n @def_gl{UNPACK_ALIGNMENT}, \n @def_gl{UNPACK_IMAGE_HEIGHT}, \n @def_gl{UNPACK_ROW_LENGTH}, \n @def_gl{UNPACK_SKIP_IMAGES}, \n @def_gl{UNPACK_SKIP_PIXELS}, \n @def_gl{UNPACK_SKIP_ROWS}, \n @def_gl{UNPACK_SWAP_BYTES} | not queryable, @ref PixelStorage setters only @def_gl{POINT_FADE_THRESHOLD_SIZE} | | @def_gl{POINT_SIZE_GRANULARITY}, \n @def_gl{POINT_SIZE_RANGE} | | @def_gl{POINT_SIZE} | not queryable, @ref Renderer::setPointSize() setter only diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 2e90d25e8..ea6d1f582 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -40,7 +40,6 @@ The core subset of OpenGL 2.1 should be fully implemented, except for the following: - Proxy textures -- Copying framebuffer to texture (@fn_gl{CopyTexImage2D} etc.) - Some forgotten limit queries @subsection opengl-support-30 OpenGL 3.0 @@ -132,8 +131,8 @@ GLSL 4.00 | done @extension{ARB,shader_subroutine} | | @extension{ARB,tessellation_shader} | missing some limit queries and patch parameter specification function @extension{ARB,texture_buffer_object_rgb32} | done -@extension{ARB,transform_feedback2} | missing transform feedback draw -@extension{ARB,transform_feedback3} | only advanced interleaving +@extension{ARB,transform_feedback2} | done +@extension{ARB,transform_feedback3} | missing indexed properties query @subsection opengl-support-41 OpenGL 4.1 @@ -155,7 +154,7 @@ GLSL 4.20 | done @extension{ARB,texture_compression_bptc} | done @extension{ARB,base_instance} | done @extension{ARB,shading_language_420pack} | done (shading language only) -@extension{ARB,transform_feedback_instanced} | | +@extension{ARB,transform_feedback_instanced} | done @extension{ARB,compressed_texture_pixel_storage} | done @extension{ARB,conservative_depth} | done (shading language only) @extension{ARB,internalformat_query} | | @@ -245,7 +244,7 @@ Extension | Status @extension{ARB,sparse_texture} | | @extension{ARB,pipeline_statistics_query} | | @extension{ARB,sparse_buffer} | | -@extension{ARB,transform_feedback_overflow_query} | | +@extension{ARB,transform_feedback_overflow_query} | done @extension{KHR,blend_equation_advanced} | done @extension3{KHR,blend_equation_advanced_coherent,blend_equation_advanced} | done @extension{KHR,no_error} | done @@ -258,6 +257,7 @@ Extension | Status Extension | Status ------------------------------------------- | ------ +@extension{AMD,transform_feedback3_lines_triangles} | done (nothing to do) @extension{AMD,vertex_shader_layer} | done (shading language only) @extension{AMD,shader_trinary_minmax} | done (shading language only) @extension{ATI,texture_mirror_once} | done (GL 4.4 subset) @@ -323,6 +323,7 @@ Extension | Status @es_extension{NV,shadow_samplers_cube} | done (shading language only) @es_extension{OES,depth24} | done @es_extension{OES,element_index_uint} | done +@es_extension{OES,fbo_render_mipmap} | done @es_extension{OES,rgb8_rgba8} | done (desktop-compatible subset) @es_extension{OES,texture_3D} | done @es_extension2{OES,texture_half_float_linear,OES_texture_float_linear} | done @@ -427,6 +428,7 @@ Extension | Status @webgl_extension{OES,element_index_uint} | done @webgl_extension{OES,texture_float_linear} | done @webgl_extension{OES,texture_half_float_linear} | done +@webgl_extension{OES,fbo_render_mipmap} | done @webgl_extension{WEBGL,depth_texture} | done @webgl_extension{WEBGL,draw_buffers} | done diff --git a/doc/platform.dox b/doc/platform.dox index bc58a29b4..f009e4f63 100644 --- a/doc/platform.dox +++ b/doc/platform.dox @@ -284,8 +284,6 @@ int main(int argc, char** argv) { } // Delete OpenGL context ... - - return 0; } @endcode @@ -319,6 +317,75 @@ target_link_libraries(myapplication Magnum::Context) @endcode +@section platform-windowless-contexts Manually managing windowless contexts + +In case you need to manage windowless OpenGL contexts manually (for example +to use Magnum for data processing in a thread or when having more than one +OpenGL context), there is a possibility to directly use the context wrappers +from windowless applications. Each @ref Platform::WindowlessEglApplication "Platform::Windowless*Application" +is accompanied by a @ref Platform::WindowlessEglContext "Platform::Windowless*Context" +class that manages just GL context creation, making it current and destruction. +Similarly to using custom platform toolkits above, the workflow is to first +create a GL context instance, then making it current and finally instantiating +the @ref Platform::Context instance to initialize Magnum. + +Similarly as with the applications, to simplify the porting, the library +provides `Platform::WindowlessGLContext` typedef, but only if just one +windowless application header is included. + +@attention With this approach it is possible to switch between different GL + contexts, but make sure that Magnum is used only with its OpenGL context. + +@code +int main(int argc, char** argv) { + Platform::WindowlessGLContext glContext{{}}; + glContext.makeCurrent(); + Platform::Context context{argc, argv}; + + // Your GL code ... + + // Make another context current + eglMakeCurrent(); + + // Someone else's code ... + + // Make Magnum context current again + glContext.makeCurrent(); + + // Your GL code again ... + + // Magnum context gets destroyed + // Windowless GL context gets destroyed +} +@endcode + +The main purpose of windowless contexts is threaded OpenGL, used for example +for background data processing. The workflow is to create the windowless +context on the main thread, but make it current in the worker thread. This way +the main thread state isn't affected so it can have any other GL context +current (for example for the main application rendering). See also +@ref MAGNUM_BUILD_MULTITHREADED. + +@note Context creation is not thread safe on all platforms, that's why it still + has to be done on the main thread. + +@code +int main() { + Platform::WindowlessGLContext glContext{{}}; + + std::thread worker{[&glContext]{ + glContext.makeCurrent(); + Platform::Context context{0, nullptr}; + + // Use Magnum here ... + }}; + + // Independent main application code here ... + + worker.join(); +} +@endcode + - Next page: @ref types */ } diff --git a/doc/plugins.dox b/doc/plugins.dox index 4a8432cd5..35c4b5e37 100644 --- a/doc/plugins.dox +++ b/doc/plugins.dox @@ -179,10 +179,10 @@ usage is basically the same as above, but you need to explicitly find the plugin and link it into the executable in your `CMakeLists.txt`. See @ref cmake and @ref cmake-plugins for additional information. @code -find_package(Magnum REQUIRED TgaImporter) +find_package(MagnumPlugins REQUIRED PngImporter) add_executable(MyApp ...) -target_link_libraries(MyApp ... Magnum::TgaImporter) +target_link_libraries(MyApp ... MagnumPlugins::PngImporter) @endcode The only user-visible behavioral change will be that diff --git a/doc/types.dox b/doc/types.dox index c510c8b2c..7e5f5498e 100644 --- a/doc/types.dox +++ b/doc/types.dox @@ -157,6 +157,10 @@ Complex b = Complex::rotation(60.0_degf); Other types, which don't have their GLSL equivalent, are: +- @ref QuadraticBezier2D or @ref QuadraticBezier2Dd, @ref QuadraticBezier3D + or @ref QuadraticBezier3Dd +- @ref CubicBezier2D or @ref CubicBezier2Dd, @ref CubicBezier3D + or @ref CubicBezier3Dd - @ref Complex or @ref Complexd, @ref DualComplex or @ref DualComplexd - @ref Quaternion or @ref Quaterniond, @ref DualQuaternion or @ref DualQuaterniond diff --git a/doc/utilities.dox b/doc/utilities.dox index 8533fa386..f5d1ecaff 100644 --- a/doc/utilities.dox +++ b/doc/utilities.dox @@ -28,8 +28,10 @@ namespace Magnum { @brief Command-line utilities for system information and data conversion - @subpage magnum-info -- @copybrief magnum-info +- @subpage magnum-al-info -- @copybrief magnum-al-info - @subpage magnum-distancefieldconverter -- @copybrief magnum-distancefieldconverter - @subpage magnum-fontconverter -- @copybrief magnum-fontconverter +- @subpage magnum-imageconverter -- @copybrief magnum-imageconverter */ } diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index c4af7f726..03285cb4f 100644 --- a/modules/FindCorrade.cmake +++ b/modules/FindCorrade.cmake @@ -73,7 +73,9 @@ # CORRADE_TARGET_UNIX - Defined if compiled for some Unix flavor # (Linux, BSD, OS X) # CORRADE_TARGET_APPLE - Defined if compiled for Apple platforms -# CORRADE_TARGET_IOS - Defined if compiled for iOS +# CORRADE_TARGET_IOS - Defined if compiled for iOS (device or +# simulator) +# CORRADE_TARGET_IOS_SIMULATOR - Defined if compiled for iOS Simulator # CORRADE_TARGET_WINDOWS - Defined if compiled for Windows # CORRADE_TARGET_WINDOWS_RT - Defined if compiled for Windows RT # CORRADE_TARGET_NACL - Defined if compiled for Google Chrome Native @@ -97,6 +99,7 @@ # CORRADE_USE_MODULE - Path to UseCorrade.cmake module (included # automatically) # CORRADE_TESTSUITE_XCTEST_RUNNER - Path to XCTestRunner.mm.in file +# CORRADE_TESTSUITE_ADB_RUNNER - Path to AdbRunner.sh file # CORRADE_PEDANTIC_COMPILER_OPTIONS - List of pedantic compiler options used # for targets with :prop_tgt:`CORRADE_USE_PEDANTIC_FLAGS` enabled # CORRADE_PEDANTIC_COMPILER_DEFINITIONS - List of pedantic compiler @@ -120,13 +123,21 @@ # # corrade_add_test( # ... -# [LIBRARIES ...]) +# [LIBRARIES ...] +# [FILES ...]) # # Test name is also executable name. You can also specify libraries to link # with instead of using :command:`target_link_libraries()`. # ``Corrade::TestSuite`` target is linked automatically to each test. Note # that the :command:`enable_testing()` function must be called explicitly. # +# You can list files needed by the test in the `FILES` section. The filenames +# are treated relatively to `CMAKE_CURRENT_SOURCE_DIR`. On desktop platforms +# the files are added to the :prop_test:`REQUIRED_FILES` target property. On +# Emscripten they are bundled to the executable and available in the virtual +# filesystem root. On Android they are copied along the executable to the +# target. +# # Unless :variable:`CORRADE_TESTSUITE_TARGET_XCTEST` is set, test cases on iOS # targets are created as bundles with bundle identifier set to CMake project # name by default. Use the cache variable :variable:`CORRADE_TESTSUITE_BUNDLE_IDENTIFIER_PREFIX` @@ -152,37 +163,60 @@ # Add dynamic plugin:: # # corrade_add_plugin( -# +# ";" +# ";" # # ...) # # The macro adds preprocessor directive ``CORRADE_DYNAMIC_PLUGIN``. Additional # libraries can be linked in via :command:`target_link_libraries(plugin_name ...) `. -# If ```` is set to :variable:`CMAKE_CURRENT_BINARY_DIR` -# (e.g. for testing purposes), the files are copied directly, without the need -# to perform install step. Note that the files are actually put into -# configuration-based subdirectory, i.e. ``${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}``. -# See documentation of :variable:`CMAKE_CFG_INTDIR` variable for more -# information. +# On DLL platforms, the plugin DLLs and metadata files are put into +# ````/```` and the +# ``*.lib`` files into ````/````. +# On non-DLL platforms everything is put into ````/ +# ````. +# +# corrade_add_plugin( +# +# +# +# ...) +# +# Unline the above version this puts everything into ```` on +# both DLL and non-DLL platforms. If ```` is set to +# :variable:`CMAKE_CURRENT_BINARY_DIR` (e.g. for testing purposes), the files +# are copied directly, without the need to perform install step. Note that the +# files are actually put into configuration-based subdirectory, i.e. +# ``${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}``. See documentation of +# :variable:`CMAKE_CFG_INTDIR` variable for more information. # # .. command:: corrade_add_static_plugin # # Add static plugin:: # # corrade_add_static_plugin( -# +# ";" # # ...) # # The macro adds preprocessor directive ``CORRADE_STATIC_PLUGIN``. Additional # libraries can be linked in via :command:`target_link_libraries(plugin_name ...) `. +# The ```` is ignored and included just for compatibility +# with the :command:`corrade_add_plugin` command, everything is installed into +# ````. Note that plugins built in debug configuration +# (e.g. with :variable:`CMAKE_BUILD_TYPE` set to ``Debug``) have ``"-d"`` +# suffix to make it possible to have both debug and release plugins installed +# alongside each other. +# +# corrade_add_static_plugin( +# +# +# ...) +# +# Equivalent to the above with ```` set to ````. # If ```` is set to :variable:`CMAKE_CURRENT_BINARY_DIR` (e.g. for # testing purposes), no installation rules are added. # -# Note that plugins built in debug configuration (e.g. with :variable:`CMAKE_BUILD_TYPE` -# set to ``Debug``) have ``"-d"`` suffix to make it possible to have both debug -# and release plugins installed alongside each other. -# # .. command:: corrade_find_dlls_for_libs # # Find corresponding DLLs for library files:: @@ -248,6 +282,7 @@ set(_corradeFlags TARGET_UNIX TARGET_APPLE TARGET_IOS + TARGET_IOS_SIMULATOR TARGET_WINDOWS TARGET_WINDOWS_RT TARGET_NACL @@ -271,6 +306,13 @@ if(CORRADE_TESTSUITE_TARGET_XCTEST) set(CORRADE_TESTSUITE_XCTEST_RUNNER_NEEDED CORRADE_TESTSUITE_XCTEST_RUNNER) endif() +# ADB runner file +if(CORRADE_TARGET_ANDROID) + find_file(CORRADE_TESTSUITE_ADB_RUNNER AdbRunner.sh + PATH_SUFFIXES share/corrade/TestSuite) + set(CORRADE_TESTSUITE_ADB_RUNNER_NEEDED CORRADE_TESTSUITE_ADB_RUNNER) +endif() + # CMake module dir find_path(_CORRADE_MODULE_DIR NAMES UseCorrade.cmake CorradeLibSuffix.cmake @@ -459,6 +501,7 @@ find_package_handle_standard_args(Corrade REQUIRED_VARS _CORRADE_MODULE_DIR _CORRADE_CONFIGURE_FILE ${CORRADE_TESTSUITE_XCTEST_RUNNER_NEEDED} + ${CORRADE_TESTSUITE_ADB_RUNNER_NEEDED} HANDLE_COMPONENTS) # Finalize the finding process diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 5c88350fe..439e87413 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -72,7 +72,9 @@ # WavAudioImporter - WAV audio importer plugin # distancefieldconverter - magnum-distancefieldconverter executable # fontconverter - magnum-fontconverter executable +# imageconverter - magnum-imageconverter executable # info - magnum-info executable +# al-info - magnum-al-info executable # # Example usage with specifying additional components is:: # @@ -105,6 +107,8 @@ # MAGNUM_BUILD_DEPRECATED - Defined if compiled with deprecated APIs # included # MAGNUM_BUILD_STATIC - Defined if compiled as static libraries +# MAGNUM_BUILD_MULTITHREADED - Defined if compiled in a way that allows +# having multiple thread-local Magnum contexts # MAGNUM_TARGET_GLES - Defined if compiled for OpenGL ES # MAGNUM_TARGET_GLES2 - Defined if compiled for OpenGL ES 2.0 # MAGNUM_TARGET_GLES3 - Defined if compiled for OpenGL ES 3.0 @@ -125,17 +129,30 @@ # MAGNUM_BINARY_INSTALL_DIR - Binary installation directory # MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory # MAGNUM_DATA_INSTALL_DIR - Data installation directory -# MAGNUM_PLUGINS_[DEBUG|RELEASE]_INSTALL_DIR - Plugin installation directory -# MAGNUM_PLUGINS_FONT_[DEBUG|RELEASE]_INSTALL_DIR - Font plugin installation -# directory -# 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 +# MAGNUM_PLUGINS_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Plugin binary # installation directory -# MAGNUM_PLUGINS_AUDIOIMPORTER_[DEBUG|RELEASE]_INSTALL_DIR - Audio importer -# plugin installation directory +# MAGNUM_PLUGINS_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Plugin library +# installation directory +# MAGNUM_PLUGINS_FONT_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Font plugin binary +# installation directory +# MAGNUM_PLUGINS_FONT_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Font plugin +# library installation directory +# MAGNUM_PLUGINS_FONTCONVERTER_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Font +# converter plugin binary installation directory +# MAGNUM_PLUGINS_FONTCONVERTER_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Font +# converter plugin library installation directory +# MAGNUM_PLUGINS_IMAGECONVERTER_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Image +# converter plugin binary installation directory +# MAGNUM_PLUGINS_IMAGECONVERTER_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Image +# converter plugin library installation directory +# MAGNUM_PLUGINS_IMPORTER_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Importer +# plugin binary installation directory +# MAGNUM_PLUGINS_IMPORTER_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Importer +# plugin library installation directory +# MAGNUM_PLUGINS_AUDIOIMPORTER_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Audio +# importer plugin binary installation directory +# MAGNUM_PLUGINS_AUDIOIMPORTER_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Audio +# importer plugin library installation directory # MAGNUM_INCLUDE_INSTALL_DIR - Header installation directory # MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR - Plugin header installation directory # @@ -206,6 +223,7 @@ file(READ ${_MAGNUM_CONFIGURE_FILE} _magnumConfigure) set(_magnumFlags BUILD_DEPRECATED BUILD_STATIC + BUILD_MULTITHREADED TARGET_GLES TARGET_GLES2 TARGET_GLES3 @@ -233,17 +251,24 @@ if(NOT TARGET Magnum::Magnum) # information to guess also build type of dynamic plugins if(MAGNUM_LIBRARY_DEBUG AND MAGNUM_LIBRARY_RELEASE) set(MAGNUM_LIBRARY ${MAGNUM_LIBRARY_RELEASE}) - get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY_DEBUG} PATH) + get_filename_component(_MAGNUM_PLUGINS_DIR_PREFIX ${MAGNUM_LIBRARY_DEBUG} PATH) 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) + get_filename_component(_MAGNUM_PLUGINS_DIR_PREFIX ${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) + get_filename_component(_MAGNUM_PLUGINS_DIR_PREFIX ${MAGNUM_LIBRARY_RELEASE} PATH) + endif() + + # On DLL platforms the plugins are stored in bin/ instead of lib/, modify + # _MAGNUM_PLUGINS_DIR_PREFIX accordingly + if(CORRADE_TARGET_WINDOWS) + get_filename_component(_MAGNUM_PLUGINS_DIR_PREFIX ${_MAGNUM_PLUGINS_DIR_PREFIX} PATH) + set(_MAGNUM_PLUGINS_DIR_PREFIX ${_MAGNUM_PLUGINS_DIR_PREFIX}/bin) endif() if(MAGNUM_LIBRARY_RELEASE) @@ -341,7 +366,7 @@ endif() # components from other repositories) set(_MAGNUM_LIBRARY_COMPONENTS "^(Audio|DebugTools|MeshTools|Primitives|SceneGraph|Shaders|Shapes|Text|TextureTools|AndroidApplication|GlfwApplication|GlutApplication|GlxApplication|NaClApplication|Sdl2Application|XEglApplication|WindowlessCglApplication|WindowlessEglApplication|WindowlessGlxApplication|WindowlessIosApplication|WindowlessNaClApplication|WindowlessWglApplication|WindowlessWindowsEglApplication|CglContext|EglContext|GlxContext|WglContext)$") set(_MAGNUM_PLUGIN_COMPONENTS "^(MagnumFont|MagnumFontConverter|ObjImporter|TgaImageConverter|TgaImporter|WavAudioImporter)$") -set(_MAGNUM_EXECUTABLE_COMPONENTS "^(distancefieldconverter|fontconverter|info)$") +set(_MAGNUM_EXECUTABLE_COMPONENTS "^(distancefieldconverter|fontconverter|imageconverter|info|al-info)$") # Find all components foreach(_component ${Magnum_FIND_COMPONENTS}) @@ -422,7 +447,7 @@ foreach(_component ${Magnum_FIND_COMPONENTS}) MAGNUM_${_COMPONENT}_LIBRARY_RELEASE) # Reset back - set(CMAKE_FIND_LIBRARY_PREFIXES ${_tmp_prefixes}) + set(CMAKE_FIND_LIBRARY_PREFIXES "${_tmp_prefixes}") endif() # Library location for libraries/plugins @@ -744,28 +769,41 @@ include(${CORRADE_LIB_SUFFIX_MODULE}) set(MAGNUM_BINARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin) set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) set(MAGNUM_DATA_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/magnum) -set(MAGNUM_PLUGINS_DEBUG_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d) -set(MAGNUM_PLUGINS_RELEASE_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) -set(MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fonts) -set(MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fonts) -set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fontconverters) -set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fontconverters) -set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/imageconverters) -set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/imageconverters) -set(MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/importers) -set(MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/importers) -set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/audioimporters) -set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d) +set(MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d) +set(MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum) +set(MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) +set(MAGNUM_PLUGINS_FONT_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMPORTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/audioimporters) set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum) set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/MagnumPlugins) -# Get base plugin directory from main library location -set(MAGNUM_PLUGINS_DEBUG_DIR ${_MAGNUM_LIBRARY_PATH}/magnum-d - CACHE PATH "Base directory where to look for Magnum plugins for debug builds") -set(MAGNUM_PLUGINS_RELEASE_DIR ${_MAGNUM_LIBRARY_PATH}/magnum - CACHE PATH "Base directory where to look for Magnum plugins for release builds") -set(MAGNUM_PLUGINS_DIR ${_MAGNUM_LIBRARY_PATH}/magnum${_MAGNUM_PLUGINS_DIR_SUFFIX} - CACHE PATH "Base directory where to look for Magnum plugins") +# Get base plugin directory from main library location. This is *not* PATH, +# because CMake always converts the path to an absolute location internally, +# making it impossible to specify relative paths there. Sorry in advance for +# not having the dir selection button in CMake GUI. +set(MAGNUM_PLUGINS_DEBUG_DIR ${_MAGNUM_PLUGINS_DIR_PREFIX}/magnum-d + CACHE STRING "Base directory where to look for Magnum plugins for debug builds") +set(MAGNUM_PLUGINS_RELEASE_DIR ${_MAGNUM_PLUGINS_DIR_PREFIX}/magnum + CACHE STRING "Base directory where to look for Magnum plugins for release builds") +set(MAGNUM_PLUGINS_DIR ${_MAGNUM_PLUGINS_DIR_PREFIX}/magnum${_MAGNUM_PLUGINS_DIR_SUFFIX} + CACHE STRING "Base directory where to look for Magnum plugins") # Plugin directories set(MAGNUM_PLUGINS_FONT_DIR ${MAGNUM_PLUGINS_DIR}/fonts) diff --git a/modules/FindOpenAL.cmake b/modules/FindOpenAL.cmake new file mode 100644 index 000000000..aac70fae7 --- /dev/null +++ b/modules/FindOpenAL.cmake @@ -0,0 +1,137 @@ +#.rst: +# FindOpenAL +# ---------- +# +# +# +# Locate OpenAL This module defines OPENAL_LIBRARY OPENAL_FOUND, if +# false, do not try to link to OpenAL OPENAL_INCLUDE_DIR, where to find +# the headers +# +# $OPENALDIR is an environment variable that would correspond to the +# ./configure --prefix=$OPENALDIR used in building OpenAL. +# +# Created by Eric Wing. This was influenced by the FindSDL.cmake +# module. + +#============================================================================= +# CMake - Cross Platform Makefile Generator +# Copyright 2000-2016 Kitware, Inc. +# Copyright 2000-2011 Insight Software Consortium +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +# This makes the presumption that you are include al.h like +# #include "al.h" +# and not +# #include +# The reason for this is that the latter is not entirely portable. +# Windows/Creative Labs does not by default put their headers in AL/ and +# OS X uses the convention . +# +# For Windows, Creative Labs seems to have added a registry key for their +# OpenAL 1.1 installer. I have added that key to the list of search paths, +# however, the key looks like it could be a little fragile depending on +# if they decide to change the 1.00.0000 number for bug fix releases. +# Also, they seem to have laid down groundwork for multiple library platforms +# which puts the library in an extra subdirectory. Currently there is only +# Win32 and I have hardcoded that here. This may need to be adjusted as +# platforms are introduced. +# The OpenAL 1.0 installer doesn't seem to have a useful key I can use. +# I do not know if the Nvidia OpenAL SDK has a registry key. +# +# For OS X, remember that OpenAL was added by Apple in 10.4 (Tiger). +# To support the framework, I originally wrote special framework detection +# code in this module which I have now removed with CMake's introduction +# of native support for frameworks. +# In addition, OpenAL is open source, and it is possible to compile on Panther. +# Furthermore, due to bugs in the initial OpenAL release, and the +# transition to OpenAL 1.1, it is common to need to override the built-in +# framework. +# Per my request, CMake should search for frameworks first in +# the following order: +# ~/Library/Frameworks/OpenAL.framework/Headers +# /Library/Frameworks/OpenAL.framework/Headers +# /System/Library/Frameworks/OpenAL.framework/Headers +# +# On OS X, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# OPENAL_LIBRARY to override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. + +find_path(OPENAL_INCLUDE_DIR al.h + HINTS + ENV OPENALDIR + # The AL was added in order to make the module working for Emscripten on OSX. + # Not sure why include/AL wasn't enough. + PATH_SUFFIXES include/AL include/OpenAL include AL + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir] +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_OpenAL_ARCH_DIR libs/Win64) +else() + set(_OpenAL_ARCH_DIR libs/Win32) +endif() + +if(NOT CORRADE_TARGET_EMSCRIPTEN) + find_library(OPENAL_LIBRARY + NAMES OpenAL al openal OpenAL32 + HINTS + ENV OPENALDIR + PATH_SUFFIXES lib64 lib libs64 libs ${_OpenAL_ARCH_DIR} + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw + /opt/local + /opt/csw + /opt + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir] + ) + set(OPENAL_LIBRARY_NEEDED OPENAL_LIBRARY) +endif() + +unset(_OpenAL_ARCH_DIR) + +# handle the QUIETLY and REQUIRED arguments and set OPENAL_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenAL DEFAULT_MSG ${OPENAL_LIBRARY_NEEDED} OPENAL_INCLUDE_DIR) + +mark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR) diff --git a/modules/FindSDL2.cmake b/modules/FindSDL2.cmake index 172965181..2194d0750 100644 --- a/modules/FindSDL2.cmake +++ b/modules/FindSDL2.cmake @@ -43,14 +43,19 @@ if(CORRADE_TARGET_EMSCRIPTEN) set(_SDL2_PATH_SUFFIXES SDL) else() + # Precompiled libraries for Windows are in x86/x64 subdirectories + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_SDL_LIBRARY_PATH_SUFFIX lib/x64) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(_SDL_LIBRARY_PATH_SUFFIX lib/x86) + endif() + find_library(SDL2_LIBRARY # Compiling SDL2 from scratch on OSX creates dead libSDL2.so symlink # which CMake somehow prefers before the SDL2-2.0.dylib file. Making # the dylib first so it is preferred. NAMES SDL2-2.0 SDL2 - - # Precompiled libraries for Windows are in x86/x64 subdirectories - PATH_SUFFIXES lib/x86 lib/x64) + PATH_SUFFIXES ${_SDL_LIBRARY_PATH_SUFFIX}) set(SDL2_LIBRARY_NEEDED SDL2_LIBRARY) set(_SDL2_PATH_SUFFIXES SDL2) endif() @@ -80,6 +85,7 @@ if(CORRADE_TARGET_IOS) set(_SDL2_FRAMEWORK_LIBRARIES ) foreach(framework ${_SDL2_FRAMEWORKS}) find_library(_SDL2_${framework}_LIBRARY ${framework}) + mark_as_advanced(_SDL2_${framework}_LIBRARY) list(APPEND _SDL2_FRAMEWORK_LIBRARIES ${_SDL2_${framework}_LIBRARY}) list(APPEND _SDL2_FRAMEWORK_LIBRARY_NAMES _SDL2_${framework}_LIBRARY) endforeach() diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index 428e6bb08..d3a836627 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -41,7 +41,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON \ -G Ninja diff --git a/package/archlinux/PKGBUILD-android-arm b/package/archlinux/PKGBUILD-android-arm index 01b7a6154..a3b7d01cf 100644 --- a/package/archlinux/PKGBUILD-android-arm +++ b/package/archlinux/PKGBUILD-android-arm @@ -34,7 +34,8 @@ build() { -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_ANDROIDAPPLICATION=ON \ - -DWITH_EGLCONTEXT=ON + -DWITH_EGLCONTEXT=ON \ + -DBUILD_TESTS=ON ninja } diff --git a/package/archlinux/PKGBUILD-android-x86 b/package/archlinux/PKGBUILD-android-x86 index 5862419ef..a5fdd4d47 100644 --- a/package/archlinux/PKGBUILD-android-x86 +++ b/package/archlinux/PKGBUILD-android-x86 @@ -34,7 +34,8 @@ build() { -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_ANDROIDAPPLICATION=ON \ - -DWITH_EGLCONTEXT=ON + -DWITH_EGLCONTEXT=ON \ + -DBUILD_TESTS=ON ninja } diff --git a/package/archlinux/PKGBUILD-clang b/package/archlinux/PKGBUILD-clang index 29a127c45..66912ca4f 100644 --- a/package/archlinux/PKGBUILD-clang +++ b/package/archlinux/PKGBUILD-clang @@ -44,7 +44,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON ninja diff --git a/package/archlinux/PKGBUILD-clang-libc++ b/package/archlinux/PKGBUILD-clang-libc++ index bcbef4df6..cb00c89be 100644 --- a/package/archlinux/PKGBUILD-clang-libc++ +++ b/package/archlinux/PKGBUILD-clang-libc++ @@ -47,7 +47,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON ninja diff --git a/package/archlinux/PKGBUILD-emscripten b/package/archlinux/PKGBUILD-emscripten index 12445e06c..b7f99e3a9 100644 --- a/package/archlinux/PKGBUILD-emscripten +++ b/package/archlinux/PKGBUILD-emscripten @@ -7,7 +7,7 @@ arch=('any') url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('emscripten-corrade') -makedepends=('cmake' 'emscripten' 'corrade') +makedepends=('cmake' 'emscripten' 'corrade' 'ninja') options=('!strip' '!buildflags') _rootdir=$startdir/../../ @@ -19,7 +19,8 @@ build() { cmake .. \ -DCMAKE_TOOLCHAIN_FILE="$_rootdir/toolchains/generic/Emscripten.cmake" \ - -DCMAKE_PREFIX_PATH=/usr/lib/emscripten/system + -DCMAKE_PREFIX_PATH=/usr/lib/emscripten/system \ + -G Ninja fi cd "$_rootdir/build-emscripten" @@ -27,15 +28,23 @@ build() { cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/lib/emscripten/system \ + -DWITH_AUDIO=ON \ -DWITH_SDL2APPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ - -DWITH_TGAIMPORTER=ON - make + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=ON \ + -DBUILD_TESTS=ON + ninja +} + +check() { + cd "$_rootdir/build-emscripten" + CORRADE_TEST_COLOR=ON ctest --output-on-failure -E ALTest } package() { cd "$_rootdir/build-emscripten" - DESTDIR="$pkgdir/" make install + DESTDIR="$pkgdir/" ninja install } diff --git a/package/archlinux/PKGBUILD-emscripten-webgl2 b/package/archlinux/PKGBUILD-emscripten-webgl2 index 5025f842d..f52f18ee2 100644 --- a/package/archlinux/PKGBUILD-emscripten-webgl2 +++ b/package/archlinux/PKGBUILD-emscripten-webgl2 @@ -7,7 +7,7 @@ arch=('any') url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('emscripten-corrade') -makedepends=('cmake' 'emscripten' 'corrade') +makedepends=('cmake' 'emscripten' 'corrade' 'ninja') options=('!strip' '!buildflags') _rootdir=$startdir/../../ @@ -19,7 +19,8 @@ build() { cmake .. \ -DCMAKE_TOOLCHAIN_FILE="$_rootdir/toolchains/generic/Emscripten.cmake" \ - -DCMAKE_PREFIX_PATH=/usr/lib/emscripten/system + -DCMAKE_PREFIX_PATH=/usr/lib/emscripten/system \ + -G Ninja fi cd "$_rootdir/build-emscripten-webgl2" @@ -28,16 +29,23 @@ build() { -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/lib/emscripten/system \ -DTARGET_GLES2=OFF \ + -DWITH_AUDIO=ON \ -DWITH_SDL2APPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ - -DWITH_WAVAUDIOIMPORTER=ON - make + -DWITH_WAVAUDIOIMPORTER=ON \ + -DBUILD_TESTS=ON + ninja +} + +check() { + cd "$_rootdir/build-emscripten" + CORRADE_TEST_COLOR=ON ctest --output-on-failure -E ALTest } package() { cd "$_rootdir/build-emscripten-webgl2" - DESTDIR="$pkgdir/" make install + DESTDIR="$pkgdir/" ninja install } diff --git a/package/archlinux/PKGBUILD-es2 b/package/archlinux/PKGBUILD-es2 index 572e3e47f..3b13bc5f8 100644 --- a/package/archlinux/PKGBUILD-es2 +++ b/package/archlinux/PKGBUILD-es2 @@ -24,13 +24,18 @@ build() { -DTARGET_GLES2=ON \ -DWITH_AUDIO=ON \ -DWITH_XEGLAPPLICATION=ON \ + -DWITH_WINDOWLESSEGLAPPLICATION=ON \ -DWITH_EGLCONTEXT=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_IMAGECONVERTER=ON \ + -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ + -DBUILD_GL_TESTS=ON \ -G Ninja ninja } diff --git a/package/archlinux/PKGBUILD-es2desktop b/package/archlinux/PKGBUILD-es2desktop index 6642f10a1..a85da86df 100644 --- a/package/archlinux/PKGBUILD-es2desktop +++ b/package/archlinux/PKGBUILD-es2desktop @@ -36,7 +36,9 @@ build() { -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON \ -G Ninja diff --git a/package/archlinux/PKGBUILD-es3 b/package/archlinux/PKGBUILD-es3 index 132ffaa72..927a9d978 100644 --- a/package/archlinux/PKGBUILD-es3 +++ b/package/archlinux/PKGBUILD-es3 @@ -24,13 +24,18 @@ build() { -DTARGET_GLES2=OFF \ -DWITH_AUDIO=ON \ -DWITH_XEGLAPPLICATION=ON \ + -DWITH_WINDOWLESSEGLAPPLICATION=ON \ -DWITH_EGLCONTEXT=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_IMAGECONVERTER=ON \ + -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ + -DBUILD_GL_TESTS=ON \ -G Ninja ninja } diff --git a/package/archlinux/PKGBUILD-es3desktop b/package/archlinux/PKGBUILD-es3desktop index 31e7254ff..a50298c31 100644 --- a/package/archlinux/PKGBUILD-es3desktop +++ b/package/archlinux/PKGBUILD-es3desktop @@ -36,7 +36,9 @@ build() { -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON \ -G Ninja diff --git a/package/archlinux/PKGBUILD-gcc47 b/package/archlinux/PKGBUILD-gcc47 index cdb125d4c..9789e14b2 100644 --- a/package/archlinux/PKGBUILD-gcc47 +++ b/package/archlinux/PKGBUILD-gcc47 @@ -49,7 +49,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON ninja diff --git a/package/archlinux/PKGBUILD-mingw-w64 b/package/archlinux/PKGBUILD-mingw-w64 index 7f57334d2..61087015c 100644 --- a/package/archlinux/PKGBUILD-mingw-w64 +++ b/package/archlinux/PKGBUILD-mingw-w64 @@ -33,7 +33,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON \ -G Ninja @@ -59,7 +61,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON \ -G Ninja diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index 6886a63fe..bc2afa661 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -37,7 +37,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON \ -G Ninja @@ -63,7 +65,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ -DBUILD_TESTS=ON \ -DBUILD_GL_TESTS=ON \ -G Ninja diff --git a/package/archlinux/magnum-git/PKGBUILD b/package/archlinux/magnum-git/PKGBUILD index bd7852a71..d0d135244 100644 --- a/package/archlinux/magnum-git/PKGBUILD +++ b/package/archlinux/magnum-git/PKGBUILD @@ -38,7 +38,9 @@ build() { -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ - -DWITH_MAGNUMINFO=ON + -DWITH_IMAGECONVERTER=ON \ + -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON make } diff --git a/package/ci/appveyor-desktop-gles.bat b/package/ci/appveyor-desktop-gles.bat new file mode 100644 index 000000000..3dda4e281 --- /dev/null +++ b/package/ci/appveyor-desktop-gles.bat @@ -0,0 +1,48 @@ +call "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat" x64 || exit /b +set PATH=%APPVEYOR_BUILD_FOLDER%/openal/bin/Win64;%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH% + +rem Build Corrade +git clone --depth 1 git://github.com/mosra/corrade.git || exit /b +cd corrade || exit /b +mkdir build && cd build || exit /b +cmake .. ^ + -DCMAKE_BUILD_TYPE=Debug ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DWITH_INTERCONNECT=OFF ^ + -G Ninja || exit /b +cmake --build . || exit /b +cmake --build . --target install || exit /b +cd .. && cd .. + +rem Build +mkdir build && cd build || exit /b +cmake .. ^ + -DCMAKE_BUILD_TYPE=Debug ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DCMAKE_PREFIX_PATH="%APPVEYOR_BUILD_FOLDER%/openal" ^ + -DTARGET_GLES=ON ^ + -DTARGET_GLES2=%TARGET_GLES2% ^ + -DTARGET_DESKTOP_GLES=ON ^ + -DWITH_AUDIO=ON ^ + -DWITH_SDL2APPLICATION=OFF ^ + -DWITH_WINDOWLESSWGLAPPLICATION=ON ^ + -DWITH_WGLCONTEXT=ON ^ + -DWITH_MAGNUMFONT=ON ^ + -DWITH_MAGNUMFONTCONVERTER=ON ^ + -DWITH_OBJIMPORTER=ON ^ + -DWITH_TGAIMAGECONVERTER=ON ^ + -DWITH_TGAIMPORTER=ON ^ + -DWITH_WAVAUDIOIMPORTER=ON ^ + -DWITH_DISTANCEFIELDCONVERTER=OFF ^ + -DWITH_FONTCONVERTER=OFF ^ + -DWITH_IMAGECONVERTER=ON ^ + -DWITH_MAGNUMINFO=ON ^ + -DWITH_AL_INFO=ON ^ + -DBUILD_TESTS=ON ^ + -DBUILD_GL_TESTS=ON ^ + -G Ninja || exit /b +cmake --build . || exit /b +cmake --build . --target install || exit /b + +rem Test +ctest -V -E GLTest || exit /b diff --git a/package/ci/appveyor-desktop-mingw.bat b/package/ci/appveyor-desktop-mingw.bat new file mode 100644 index 000000000..f8675dbff --- /dev/null +++ b/package/ci/appveyor-desktop-mingw.bat @@ -0,0 +1,46 @@ +rem Workaround for CMake not wanting sh.exe on PATH for MinGW. AARGH. +set PATH=%PATH:C:\Program Files\Git\usr\bin;=% +set PATH=C:\tools\mingw64\bin;%APPVEYOR_BUILD_FOLDER%/openal/bin/Win64;%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH% + +rem Build Corrade. Could not get Ninja to work, meh. +git clone --depth 1 git://github.com/mosra/corrade.git || exit /b +cd corrade || exit /b +mkdir build && cd build || exit /b +cmake .. ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DWITH_INTERCONNECT=OFF ^ + -G "MinGW Makefiles" || exit /b +cmake --build . -- -j || exit /b +cmake --build . --target install -- -j || exit /b +cd .. && cd .. + +rem Build +mkdir build && cd build || exit /b +cmake .. ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DCMAKE_PREFIX_PATH="%APPVEYOR_BUILD_FOLDER%/SDL;%APPVEYOR_BUILD_FOLDER%/openal" ^ + -DWITH_AUDIO=ON ^ + -DWITH_SDL2APPLICATION=ON ^ + -DWITH_WINDOWLESSWGLAPPLICATION=ON ^ + -DWITH_WGLCONTEXT=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_IMAGECONVERTER=ON ^ + -DWITH_MAGNUMINFO=ON ^ + -DWITH_AL_INFO=ON ^ + -DBUILD_TESTS=ON ^ + -DBUILD_GL_TESTS=ON ^ + -G "MinGW Makefiles" || exit /b +cmake --build . -- -j || exit /b +cmake --build . --target install -- -j || exit /b + +rem Test +ctest -V -E GLTest || exit /b diff --git a/package/ci/appveyor-desktop.bat b/package/ci/appveyor-desktop.bat new file mode 100644 index 000000000..a7d55890e --- /dev/null +++ b/package/ci/appveyor-desktop.bat @@ -0,0 +1,45 @@ +call "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat" x64 || exit /b +set PATH=%APPVEYOR_BUILD_FOLDER%/openal/bin/Win64;%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH% + +rem Build Corrade +git clone --depth 1 git://github.com/mosra/corrade.git || exit /b +cd corrade || exit /b +mkdir build && cd build || exit /b +cmake .. ^ + -DCMAKE_BUILD_TYPE=Debug ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DWITH_INTERCONNECT=OFF ^ + -G Ninja || exit /b +cmake --build . || exit /b +cmake --build . --target install || exit /b +cd .. && cd .. + +rem Build +mkdir build && cd build || exit /b +cmake .. ^ + -DCMAKE_BUILD_TYPE=Debug ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DCMAKE_PREFIX_PATH="%APPVEYOR_BUILD_FOLDER%/SDL;%APPVEYOR_BUILD_FOLDER%/openal" ^ + -DWITH_AUDIO=ON ^ + -DWITH_SDL2APPLICATION=ON ^ + -DWITH_WINDOWLESSWGLAPPLICATION=ON ^ + -DWITH_WGLCONTEXT=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_IMAGECONVERTER=ON ^ + -DWITH_MAGNUMINFO=ON ^ + -DWITH_AL_INFO=ON ^ + -DBUILD_TESTS=ON ^ + -DBUILD_GL_TESTS=ON ^ + -G Ninja || exit /b +cmake --build . || exit /b +cmake --build . --target install || exit /b + +rem Test +ctest -V -E GLTest || exit /b diff --git a/package/ci/appveyor-rt.bat b/package/ci/appveyor-rt.bat new file mode 100644 index 000000000..760f1d64f --- /dev/null +++ b/package/ci/appveyor-rt.bat @@ -0,0 +1,76 @@ +call "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat" x64 || exit /b +set PATH=%APPVEYOR_BUILD_FOLDER%\deps-native\bin;%PATH% + +rem Build ANGLE +git clone --depth 1 git://github.com/MSOpenTech/angle.git || exit /b +cd angle\winrt\10\src || exit /b +msbuild angle.sln /p:Configuration=Release || exit /b +cd ..\..\..\.. || exit /b + +rem Build SDL +appveyor DownloadFile https://www.libsdl.org/release/SDL2-2.0.4.zip || exit /b +7z x SDL2-2.0.4.zip || exit /b +ren SDL2-2.0.4 SDL || exit /b +cd SDL/VisualC-WinRT/UWP_VS2015 || exit/b +msbuild /p:Configuration=Release || exit /b +cd ..\..\.. + +git clone --depth 1 git://github.com/mosra/corrade.git || exit /b +cd corrade || exit /b + +rem Build native corrade-rc +mkdir build && cd build || exit /b +cmake .. ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps-native ^ + -DWITH_INTERCONNECT=OFF ^ + -DWITH_PLUGINMANAGER=OFF ^ + -DWITH_TESTSUITE=OFF ^ + -G Ninja || exit /b +cmake --build . --target install || exit /b +cd .. || exit /b + +rem Crosscompile Corrade +mkdir build-rt && cd build-rt || exit /b +cmake .. ^ + -DCMAKE_SYSTEM_NAME=WindowsStore ^ + -DCMAKE_SYSTEM_VERSION=10.0 ^ + -DCORRADE_RC_EXECUTABLE=%APPVEYOR_BUILD_FOLDER%/deps-native/bin/corrade-rc.exe ^ + -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DWITH_INTERCONNECT=OFF ^ + -DBUILD_STATIC=ON ^ + -G "Visual Studio 14 2015" -A x64 || exit /b +cmake --build . --config Release --target install -- /m /v:m || exit /b +cd .. || exit /b + +cd .. || exit /b + +rem Crosscompile +mkdir build-rt && cd build-rt || exit /b +cmake .. ^ + -DCMAKE_SYSTEM_NAME=WindowsStore ^ + -DCMAKE_SYSTEM_VERSION=10.0 ^ + -DCORRADE_RC_EXECUTABLE=%APPVEYOR_BUILD_FOLDER%/deps-native/bin/corrade-rc.exe ^ + -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%/deps ^ + -DEGL_LIBRARY=%APPVEYOR_BUILD_FOLDER%/angle/winrt/10/src/Release_x64/lib/libEGL.lib ^ + -DEGL_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%/angle/include ^ + -DOPENGLES2_LIBRARY=%APPVEYOR_BUILD_FOLDER%/angle/winrt/10/src/Release_x64/lib/libGLESv2.lib ^ + -DOPENGLES2_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%/angle/include ^ + -DOPENGLES3_LIBRARY=%APPVEYOR_BUILD_FOLDER%/angle/winrt/10/src/Release_x64/lib/libGLESv2.lib ^ + -DOPENGLES3_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%/angle/include ^ + -DSDL2_LIBRARY=%APPVEYOR_BUILD_FOLDER%/SDL/VisualC-WinRT/UWP_VS2015/X64/Release/SDL-UWP/SDL2.lib ^ + -DSDL2_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%/SDL/include ^ + -DWITH_AUDIO=OFF ^ + -DWITH_SDL2APPLICATION=ON ^ + -DWITH_MAGNUMFONT=ON ^ + -DWITH_MAGNUMFONTCONVERTER=ON ^ + -DWITH_OBJIMPORTER=ON ^ + -DWITH_TGAIMAGECONVERTER=ON ^ + -DWITH_TGAIMPORTER=ON ^ + -DWITH_WAVAUDIOIMPORTER=OFF ^ + -DTARGET_GLES2=%TARGET_GLES2% ^ + -DBUILD_TESTS=ON ^ + -DBUILD_STATIC=ON ^ + -DBUILD_PLUGINS_STATIC=ON ^ + -G "Visual Studio 14 2015" -A x64 || exit /b +cmake --build . --config Release -- /m /v:m || exit /b diff --git a/package/ci/appveyor.yml b/package/ci/appveyor.yml index e8efe86fc..674932a2a 100644 --- a/package/ci/appveyor.yml +++ b/package/ci/appveyor.yml @@ -1,16 +1,23 @@ # kate: indent-width 2; -version: '{branch}-{build}' - -skip_tags: true -shallow_clone: true clone_depth: 1 os: Visual Studio 2015 environment: matrix: - - BUILD_STATIC: OFF + - TARGET: desktop + COMPILER: msvc + - TARGET: desktop + COMPILER: mingw + - TARGET: desktop-gles + TARGET_GLES2: ON + - TARGET: desktop-gles + TARGET_GLES2: OFF + - TARGET: rt + TARGET_GLES2: ON + - TARGET: rt + TARGET_GLES2: OFF notifications: - provider: Webhook @@ -20,51 +27,29 @@ notifications: on_build_status_changed: true install: -- call "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat" -- set PATH=C:/Sys/bin;C:/tools/ninja;%APPVEYOR_BUILD_FOLDER%/openal/bin/Win32;%PATH% - -# Ninja - cinst ninja +- set PATH=C:/tools/ninja;%PATH% +- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "mingw" cinst mingw /f >nul # OpenAL -- appveyor DownloadFile http://kcat.strangesoft.net/openal-binaries/openal-soft-1.17.2-bin.zip -- 7z x openal-soft-1.17.2-bin.zip -- ren openal-soft-1.17.2-bin openal -- ren openal\bin\Win32\soft_oal.dll OpenAL32.dll -- echo [General] > %APPDATA%/alsoft.ini -- echo drivers=null >> %APPDATA%/alsoft.ini +- IF NOT "%TARGET%" == "rt" IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\openal-soft-1.17.2-bin.zip appveyor DownloadFile http://kcat.strangesoft.net/openal-binaries/openal-soft-1.17.2-bin.zip +- IF NOT "%TARGET%" == "rt" 7z x openal-soft-1.17.2-bin.zip && ren openal-soft-1.17.2-bin openal && echo [General] > %APPDATA%/alsoft.ini & echo drivers=null >> %APPDATA%/alsoft.ini +- IF "%TARGET%" == "desktop" ren openal\bin\Win64\soft_oal.dll OpenAL32.dll +- IF "%TARGET%" == "desktop-gles" ren openal\bin\Win64\soft_oal.dll OpenAL32.dll # SDL2 -- appveyor DownloadFile http://www.libsdl.org/release/SDL2-devel-2.0.3-VC.zip -- 7z x SDL2-devel-2.0.3-VC.zip -- ren SDL2-2.0.3 SDL - -# Corrade -- git clone --depth 1 git://github.com/mosra/corrade.git -- cd corrade -- mkdir build -- cd build -- cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=C:/Sys -DBUILD_STATIC=%BUILD_STATIC% -G Ninja -- cmake --build . -- cmake --build . --target install -- cd .. -- cd .. +- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "msvc" IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\SDL2-devel-2.0.4-VC.zip appveyor DownloadFile http://www.libsdl.org/release/SDL2-devel-2.0.4-VC.zip +- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "msvc" 7z x SDL2-devel-2.0.4-VC.zip && ren SDL2-2.0.4 SDL +- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "mingw" IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\SDL2-devel-2.0.4-mingw.tar.gz appveyor DownloadFile http://libsdl.org/release/SDL2-devel-2.0.4-mingw.tar.gz +- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "mingw" 7z x SDL2-devel-2.0.4-mingw.tar.gz & 7z x SDL2-devel-2.0.4-mingw.tar & ren SDL2-2.0.4 SDL build_script: -- mkdir build -- cd build -- cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=C:/Sys -DCMAKE_PREFIX_PATH="%APPVEYOR_BUILD_FOLDER%/SDL;%APPVEYOR_BUILD_FOLDER%/openal" -DWITH_AUDIO=ON -DWITH_SDL2APPLICATION=ON -DWITH_WINDOWLESSWGLAPPLICATION=ON -DWITH_WGLCONTEXT=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_STATIC=%BUILD_STATIC% -DBUILD_TESTS=ON -DBUILD_GL_TESTS=ON -G Ninja -- cmake --build . -- cmake --build . --target install -- cmake . -DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/Deploy -DBUILD_TESTS=OFF -- cmake --build . --target install -- cd ../Deploy -- 7z a ../magnum.zip * - -test_script: -- cd %APPVEYOR_BUILD_FOLDER%/build -- SET fail=0 -- ctest --output-on-failure -E GLTest || SET fail=1 & ver > nul -- cd %APPVEYOR_BUILD_FOLDER% -- appveyor PushArtifact magnum.zip -- exit %fail% +- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "msvc" call package\ci\appveyor-desktop.bat +- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "mingw" call package\ci\appveyor-desktop-mingw.bat +- IF "%TARGET%" == "desktop-gles" call package\ci\appveyor-desktop-gles.bat +- IF "%TARGET%" == "rt" call package\ci\appveyor-rt.bat + +cache: +- SDL2-devel-2.0.4-VC.zip +- SDL2-devel-2.0.4-mingw.zip +- openal-soft-1.17.2-bin.zip diff --git a/package/ci/jenkins.xml b/package/ci/jenkins.xml index 4f76bf63e..835565b94 100644 --- a/package/ci/jenkins.xml +++ b/package/ci/jenkins.xml @@ -102,27 +102,22 @@ fi if [ ${gl} = "desktop" ] ; then desktop_flag=ON es_flag=OFF - windowless_flag=ON elif [ ${gl} = "es2" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON" desktop_flag=OFF es_flag=ON - windowless_flag=OFF elif [ ${gl} = "es2desktop" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON -DTARGET_DESKTOP_GLES=ON" desktop_flag=OFF es_flag=OFF - windowless_flag=ON elif [ ${gl} = "es3" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF" desktop_flag=OFF es_flag=ON - windowless_flag=OFF elif [ ${gl} = "es3desktop" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF -DTARGET_DESKTOP_GLES=ON" desktop_flag=OFF es_flag=OFF - windowless_flag=ON fi mkdir -p build-${compiler}-${libraries}-${compatibility}-${gl} @@ -136,7 +131,7 @@ cmake .. \ -DCMAKE_CXX_COMPILER=${compiler_binary} \ "${compiler_flags[@]}" \ -DBUILD_TESTS=ON \ - -DBUILD_GL_TESTS=${windowless_flag} \ + -DBUILD_GL_TESTS=ON \ -DBUILD_DEPRECATED=${deprecated_build_flag} \ ${static_build_flag} \ ${gl_flags} \ @@ -156,7 +151,7 @@ cmake .. \ -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=${desktop_flag} \ -DWITH_FONTCONVERTER=${desktop_flag} \ - -DWITH_MAGNUMINFO=${windowless_flag} \ + -DWITH_MAGNUMINFO=ON \ -G Ninja ninja diff --git a/package/ci/travis-android-arm.sh b/package/ci/travis-android-arm.sh new file mode 100755 index 000000000..f3e696481 --- /dev/null +++ b/package/ci/travis-android-arm.sh @@ -0,0 +1,60 @@ +#!/bin/bash +set -ev + +git submodule update --init + +# Corrade +git clone --depth 1 git://github.com/mosra/corrade.git +cd corrade + +# Build native corrade-rc +mkdir build && cd build +cmake .. \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps-native \ + -DCMAKE_INSTALL_RPATH=$HOME/deps-native/lib \ + -DCMAKE_BUILD_TYPE=Release \ + -DWITH_INTERCONNECT=OFF \ + -DWITH_PLUGINMANAGER=OFF \ + -DWITH_TESTSUITE=OFF +make -j install +cd .. + +# Crosscompile Corrade +mkdir build-android-arm && cd build-android-arm +ANDROID_NDK=$TRAVIS_BUILD_DIR/android-ndk-r10e cmake .. \ + -DCMAKE_TOOLCHAIN_FILE=../toolchains/generic/Android-ARM.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCORRADE_RC_EXECUTABLE=$HOME/deps-native/bin/corrade-rc \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps \ + -DWITH_INTERCONNECT=OFF +make -j install +cd .. + +cd .. + +# Crosscompile +mkdir build-android-arm && cd build-android-arm +ANDROID_NDK=$TRAVIS_BUILD_DIR/android-ndk-r10e cmake .. \ + -DCMAKE_TOOLCHAIN_FILE=../toolchains/generic/Android-ARM.cmake \ + -DCORRADE_RC_EXECUTABLE=$HOME/deps-native/bin/corrade-rc \ + -DCMAKE_PREFIX_PATH=$HOME/deps \ + -DCMAKE_FIND_ROOT_PATH=$HOME/deps \ + -DCMAKE_BUILD_TYPE=Release \ + -DTARGET_GLES2=$TARGET_GLES2 \ + -DWITH_AUDIO=OFF \ + -DWITH_ANDROIDAPPLICATION=ON \ + -DWITH_EGLCONTEXT=ON \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=OFF \ + -DBUILD_TESTS=ON +make -j${JOBS_LIMIT} + +# Start simulator and run tests +echo no | android create avd --force -n test -t android-19 --abi armeabi-v7a +emulator -avd test -no-audio -no-window & +android-wait-for-emulator +CORRADE_TEST_COLOR=ON ctest -V diff --git a/package/ci/travis-desktop-gles.sh b/package/ci/travis-desktop-gles.sh new file mode 100755 index 000000000..91859ebc9 --- /dev/null +++ b/package/ci/travis-desktop-gles.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -ev + +# Corrade +git clone --depth 1 git://github.com/mosra/corrade.git +cd corrade +mkdir build && cd build +cmake .. \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps \ + -DCMAKE_INSTALL_RPATH=$HOME/deps/lib \ + -DCMAKE_BUILD_TYPE=Release \ + -DWITH_INTERCONNECT=OFF +make -j install +cd ../.. + +mkdir build && cd build +cmake .. \ + -DCMAKE_CXX_FLAGS=$COVERAGE \ + -DCMAKE_PREFIX_PATH="$HOME/deps" \ + -DCMAKE_BUILD_TYPE=Release \ + -DTARGET_GLES=ON \ + -DTARGET_GLES2=$TARGET_GLES2 \ + -DTARGET_DESKTOP_GLES=ON \ + -DWITH_AUDIO=ON \ + -DWITH_GLFWAPPLICATION=OFF \ + -DWITH_SDL2APPLICATION=OFF \ + -DWITH_WINDOWLESS${PLATFORM_GL_API}APPLICATION=ON \ + -DWITH_${PLATFORM_GL_API}CONTEXT=ON \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_DISTANCEFIELDCONVERTER=OFF \ + -DWITH_FONTCONVERTER=OFF \ + -DWITH_IMAGECONVERTER=ON \ + -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ + -DBUILD_TESTS=ON \ + -DBUILD_GL_TESTS=ON +make -j${JOBS_LIMIT} +CORRADE_TEST_COLOR=ON ctest -V -E GLTest diff --git a/package/ci/travis-desktop.sh b/package/ci/travis-desktop.sh new file mode 100755 index 000000000..0b3b0b155 --- /dev/null +++ b/package/ci/travis-desktop.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -ev + +# Corrade +git clone --depth 1 git://github.com/mosra/corrade.git +cd corrade +mkdir build && cd build +cmake .. \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps \ + -DCMAKE_INSTALL_RPATH=$HOME/deps/lib \ + -DCMAKE_BUILD_TYPE=Debug \ + -DWITH_INTERCONNECT=OFF +make -j install +cd ../.. + +mkdir build && cd build +cmake .. \ + -DCMAKE_CXX_FLAGS=$COVERAGE \ + -DCMAKE_PREFIX_PATH="$HOME/deps;$HOME/sdl2;$HOME/glfw" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DWITH_AUDIO=ON \ + -DWITH_GLFWAPPLICATION=ON \ + -DWITH_SDL2APPLICATION=ON \ + -DWITH_WINDOWLESS${PLATFORM_GL_API}APPLICATION=ON \ + -DWITH_${PLATFORM_GL_API}CONTEXT=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_IMAGECONVERTER=ON \ + -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON \ + -DBUILD_TESTS=ON \ + -DBUILD_GL_TESTS=ON +make -j${JOBS_LIMIT} +CORRADE_TEST_COLOR=ON ctest -V -E GLTest diff --git a/package/ci/travis-emscripten.sh b/package/ci/travis-emscripten.sh new file mode 100755 index 000000000..545e02927 --- /dev/null +++ b/package/ci/travis-emscripten.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -ev + +git submodule update --init + +# Corrade +git clone --depth 1 git://github.com/mosra/corrade.git +cd corrade + +# Build native corrade-rc +mkdir build && cd build +cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps-native \ + -DCMAKE_INSTALL_RPATH=$HOME/deps-native/lib \ + -DWITH_INTERCONNECT=OFF \ + -DWITH_PLUGINMANAGER=OFF \ + -DWITH_TESTSUITE=OFF +make -j install +cd .. + +# Crosscompile Corrade +mkdir build-emscripten && cd build-emscripten +cmake .. \ + -DCORRADE_RC_EXECUTABLE=$HOME/deps-native/bin/corrade-rc \ + -DCMAKE_TOOLCHAIN_FILE="../../toolchains/generic/Emscripten.cmake" \ + -DEMSCRIPTEN_PREFIX=$(echo /usr/local/Cellar/emscripten/*/libexec) \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_FLAGS_RELEASE="-DNDEBUG -O1" \ + -DCMAKE_EXE_LINKER_FLAGS_RELEASE="-O1" \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps \ + -DWITH_INTERCONNECT=OFF +make -j install +cd .. + +cd .. + +# Crosscompile +mkdir build-emscripten && cd build-emscripten +cmake .. \ + -DCORRADE_RC_EXECUTABLE=$HOME/deps-native/bin/corrade-rc \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten.cmake" \ + -DEMSCRIPTEN_PREFIX=$(echo /usr/local/Cellar/emscripten/*/libexec) \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_FLAGS_RELEASE="-DNDEBUG -O1" \ + -DCMAKE_EXE_LINKER_FLAGS_RELEASE="-O1" \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps \ + -DCMAKE_FIND_ROOT_PATH=$HOME/deps \ + -DWITH_AUDIO=ON \ + -DWITH_SDL2APPLICATION=ON \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=ON \ + -DBUILD_TESTS=ON \ + -DTARGET_GLES2=$TARGET_GLES2 +make -j4 + +# Test +CORRADE_TEST_COLOR=ON ctest -V -E ALTest diff --git a/package/ci/travis-ios-simulator.sh b/package/ci/travis-ios-simulator.sh new file mode 100755 index 000000000..e770a1999 --- /dev/null +++ b/package/ci/travis-ios-simulator.sh @@ -0,0 +1,65 @@ +#!/bin/bash +set -ev + +git submodule update --init + +# Corrade +git clone --depth 1 git://github.com/mosra/corrade.git +cd corrade + +# Build native corrade-rc +mkdir build && cd build +cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps-native \ + -DCMAKE_INSTALL_RPATH=$HOME/deps-native/lib \ + -DWITH_INTERCONNECT=OFF \ + -DWITH_PLUGINMANAGER=OFF \ + -DWITH_TESTSUITE=OFF +make -j install +cd .. + +# Crosscompile Corrade +mkdir build-ios && cd build-ios +cmake .. \ + -DCMAKE_TOOLCHAIN_FILE=../../toolchains/generic/iOS.cmake \ + -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk \ + -DCMAKE_OSX_ARCHITECTURES="x86_64" \ + -DCORRADE_RC_EXECUTABLE=$HOME/deps-native/bin/corrade-rc \ + -DCMAKE_INSTALL_PREFIX=$HOME/deps \ + -DBUILD_STATIC=ON \ + -DTESTSUITE_TARGET_XCTEST=ON \ + -DWITH_INTERCONNECT=OFF \ + -G Xcode +cmake --build . --config Release --target install | xcpretty +cd ../.. + +# Crosscompile Magnum +mkdir build-ios && cd build-ios +cmake .. \ + -DCMAKE_TOOLCHAIN_FILE=../toolchains/generic/iOS.cmake \ + -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk \ + -DCMAKE_OSX_ARCHITECTURES="x86_64" \ + -DCORRADE_RC_EXECUTABLE=$HOME/deps-native/bin/corrade-rc \ + -DCMAKE_PREFIX_PATH="$HOME/deps;$TRAVIS_BUILD_DIR/sdl2" \ + -DTARGET_GLES2=$TARGET_GLES2 \ + -DWITH_AUDIO=ON \ + -DWITH_SDL2APPLICATION=ON \ + -DWITH_WINDOWLESSIOSAPPLICATION=ON \ + -DWITH_EGLCONTEXT=ON \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=ON \ + -DBUILD_STATIC=ON \ + -DBUILD_PLUGINS_STATIC=ON \ + -DBUILD_TESTS=ON \ + -DBUILD_GL_TESTS=ON \ + -G Xcode +cmake --build . --config Release | xcpretty +# TODO: find a better way to avoid +# Library not loaded: /System/Library/Frameworks/OpenGLES.framework/OpenGLES +# error +DYLD_FALLBACK_LIBRARY_PATH=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/OpenGLES.framework/ DYLD_FALLBACK_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks CORRADE_TEST_COLOR=ON ctest -V -C Release -E GLTest diff --git a/package/ci/travis.yml b/package/ci/travis.yml index b49d85c3b..300f28778 100644 --- a/package/ci/travis.yml +++ b/package/ci/travis.yml @@ -1,8 +1,82 @@ # kate: indent-width 2; -os: -- linux -- osx +matrix: + include: + - language: cpp + os: linux + compiler: gcc + env: + - TARGET=desktop + # Otherwise the job gets killed (probably because using too much memory) + - JOBS_LIMIT=4 + - language: cpp + os: linux + compiler: gcc + env: + - TARGET=desktop-gles + - TARGET_GLES2=ON + - JOBS_LIMIT=4 + # Disabled because the Ubuntu 12.04 drivers are missing some ES3 entrypoints + # Should be enabled after moving to 14.04 + #- language: cpp + #os: linux + #compiler: gcc + #env: + #- TARGET=desktop-gles + #- TARGET_GLES2=OFF + #- JOBS_LIMIT=4 + - language: cpp + os: osx + compiler: clang + env: TARGET=desktop + - language: cpp + os: osx + osx_image: xcode7.3 + env: + - TARGET=ios-simulator + - TARGET_GLES2=ON + - language: cpp + os: osx + osx_image: xcode7.3 + env: + - TARGET=ios-simulator + - TARGET_GLES2=OFF + - language: cpp + os: osx + osx_image: xcode7.3 + env: + - TARGET=emscripten + - TARGET_GLES2=ON + - language: cpp + os: osx + osx_image: xcode7.3 + env: + - TARGET=emscripten + - TARGET_GLES2=OFF + - language: android + os: linux + env: + - TARGET=android + - TARGET_GLES2=ON + # Otherwise the job gets killed (probably because using too much memory) + - JOBS_LIMIT=4 + android: + components: + - build-tools-19.0.0 + - android-19 + - sys-img-armeabi-v7a-android-19 + - language: android + os: linux + env: + - TARGET=android + - TARGET_GLES2=OFF + # Otherwise the job gets killed (probably because using too much memory) + - JOBS_LIMIT=4 + android: + components: + - build-tools-19.0.0 + - android-19 + - sys-img-armeabi-v7a-android-19 addons: apt: @@ -27,34 +101,36 @@ cache: - $HOME/sdl2 install: +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop" ]; then pip install --user cpp-coveralls && export COVERAGE="--coverage"; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi - if [ "$TRAVIS_OS_NAME" == "linux" ]; then export CXX=g++-4.7; fi - if [ "$TRAVIS_OS_NAME" == "linux" ]; then export PLATFORM_GL_API=GLX; fi -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then export PLATFORM_GL_API=CGL; fi -- printf "[General]\ndrivers=null" > ~/.alsoftrc +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "android" ]; then wget -nc http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin && chmod +x android-*.bin && ./android-*.bin -y | grep -v Extracting; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "desktop" ]; then export PLATFORM_GL_API=CGL; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then gem install xcpretty; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "emscripten" ]; then brew install emscripten && export LLVM=/usr/local/opt/emscripten/libexec/llvm/bin && emcc; fi +- if [ "$TARGET" == "desktop" ] || [ "$TARGET" == "desktop-gles" ]; then printf "[General]\ndrivers=null" > ~/.alsoftrc; fi # SDL (cached) -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install sdl2; fi -- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ ! -e "$HOME/sdl2/include" ]; then curl -O http://www.libsdl.org/release/SDL2-2.0.4.tar.gz && tar -xzvf SDL2-2.0.4.tar.gz && cd SDL2-2.0.4 && mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/sdl2 -DCMAKE_BUILD_TYPE=Release && cmake --build . --target install && cd ../..; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "desktop" ]; then brew install sdl2; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then curl -O https://www.libsdl.org/release/SDL2-2.0.4.tar.gz && tar -xzvf SDL2-2.0.4.tar.gz && cd SDL2-2.0.4/Xcode-iOS/SDL && xcodebuild -sdk iphonesimulator9.3 | xcpretty && mkdir -p ../../../sdl2/lib && cp build/Release-iphonesimulator/libSDL2.a ../../../sdl2/lib && mkdir -p ../../../sdl2/include/SDL2 && cp -R ../../include/* ../../../sdl2/include/SDL2 && cd ../../..; fi +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop" ] && [ ! -e "$HOME/sdl2/include" ]; then curl -O http://www.libsdl.org/release/SDL2-2.0.4.tar.gz && tar -xzvf SDL2-2.0.4.tar.gz && cd SDL2-2.0.4 && mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/sdl2 -DCMAKE_BUILD_TYPE=Release && cmake --build . --target install && cd ../..; fi # GLFW (cached) -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install homebrew/versions/glfw3; fi -- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ ! -e "$HOME/glfw/include" ]; then wget https://github.com/glfw/glfw/releases/download/3.1.2/glfw-3.1.2.zip && unzip glfw-3.1.2.zip && cd glfw-3.1.2 && mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/glfw -DCMAKE_BUILD_TYPE=Release -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF -DGLFW_BUILD_DOCS=OFF && cmake --build . --target install && cd ../..; fi - -# Corrade -- git clone --depth 1 git://github.com/mosra/corrade.git -- cd corrade -- mkdir build -- cd build -- cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/deps -DCMAKE_INSTALL_RPATH=$HOME/deps/lib -DCMAKE_BUILD_TYPE=Release -- cmake --build . -- cmake --build . --target install -- cd .. -- cd .. +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "desktop" ]; then brew install homebrew/versions/glfw3; fi +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop" ] && [ ! -e "$HOME/glfw/include" ]; then wget https://github.com/glfw/glfw/releases/download/3.1.2/glfw-3.1.2.zip && unzip glfw-3.1.2.zip && cd glfw-3.1.2 && mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/glfw -DCMAKE_BUILD_TYPE=Release -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF -DGLFW_BUILD_DOCS=OFF && cmake --build . --target install && cd ../..; fi script: -- mkdir build && cd build -- cmake .. -DCMAKE_PREFIX_PATH="$HOME/deps;$HOME/sdl2;$HOME/glfw" -DCMAKE_BUILD_TYPE=Release -DWITH_AUDIO=ON -DWITH_GLFWAPPLICATION=ON -DWITH_SDL2APPLICATION=ON -DWITH_WINDOWLESS${PLATFORM_GL_API}APPLICATION=ON -DWITH_${PLATFORM_GL_API}CONTEXT=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 -- cmake --build . -- ctest --output-on-failure -E GLTest +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop" ]; then ./package/ci/travis-desktop.sh; fi +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop-gles" ]; then ./package/ci/travis-desktop-gles.sh; fi +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "android" ]; then ./package/ci/travis-android-arm.sh; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "desktop" ]; then ./package/ci/travis-desktop.sh; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then ./package/ci/travis-ios-simulator.sh; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "emscripten" ]; then ./package/ci/travis-emscripten.sh; fi +# Travis somehow is not able to gather all output, try to force it using this +- sync + +after_success: +# Ignoring all stuff that needs GL context and thus can't be run on Travis +- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop" ]; then coveralls --gcov /usr/bin/gcov-4.7 -i src/ -E "(.*/(Test|MagnumExternal|Shaders|Platform)/.*|.*/src/Magnum/(AbstractFramebuffer|AbstractObject|AbstractQuery|AbstractShaderProgram|AbstractTexture|Buffer|BufferImage|BufferTexture|Context|CubeMapTexture|CubeMapTextureArray|DebugOutput|DefaultFramebuffer|Framebuffer|Mesh|MeshView|MultisampleTexture|OpenGL|PixelStorage|PrimitiveQuery|RectangleTexture|Renderbuffer|Renderer|SampleQuery|Sampler|Shader|Texture|TextureArray|TimeQuery|TransformFeedback|Implementation/BufferState|Implementation/DebugState|Implementation/driverSpecific|Implementation/FramebufferState|Implementation/maxTextureSize|Implementation/MeshState|Implementation/QueryState|Implementation/RendererState|Implementation/ShaderProgramState|Implementation/ShaderState|Implementation/State|Implementation/TextureState|Implementation/TransformFeedbackState)\\.(cpp|h))" --gcov-options '\-lp' > /dev/null; fi diff --git a/package/debian/copyright b/package/debian/copyright index e96081e1a..6abe3e562 100644 --- a/package/debian/copyright +++ b/package/debian/copyright @@ -4,7 +4,7 @@ Upstream-Contact: Vladimír Vondruš Source: https://github.com/mosra/magnum Files: * -Copyright: 2010-2015 Vladimír Vondruš +Copyright: 2010-2016 Vladimír Vondruš License: Expat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/package/debian/rules b/package/debian/rules index c20a60cdc..037062d7d 100755 --- a/package/debian/rules +++ b/package/debian/rules @@ -17,8 +17,10 @@ override_dh_auto_configure: -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_DISTANCEFIELDCONVERTER=ON \ + -DWITH_IMAGECONVERTER=ON \ -DWITH_FONTCONVERTER=ON \ - -DWITH_MAGNUMINFO=ON + -DWITH_MAGNUMINFO=ON \ + -DWITH_AL_INFO=ON # Extraordinarily coarse way to suppress error about libGL not being in # dependencies when the user has installed NVidia binary drivers which are not diff --git a/package/gentoo/dev-libs/magnum/magnum-9999.ebuild b/package/gentoo/dev-libs/magnum/magnum-9999.ebuild index d163545c0..2bd4cb643 100644 --- a/package/gentoo/dev-libs/magnum/magnum-9999.ebuild +++ b/package/gentoo/dev-libs/magnum/magnum-9999.ebuild @@ -40,8 +40,10 @@ src_configure() { -DWITH_TGAIMPORTER=ON -DWITH_WAVAUDIOIMPORTER=ON -DWITH_DISTANCEFIELDCONVERTER=ON + -DWITH_IMAGECONVERTER=ON -DWITH_FONTCONVERTER=ON -DWITH_MAGNUMINFO=ON + -DWITH_AL_INFO=ON ) cmake-utils_src_configure } diff --git a/package/homebrew/magnum.rb b/package/homebrew/magnum.rb index e9e0095bc..8eb0261e0 100644 --- a/package/homebrew/magnum.rb +++ b/package/homebrew/magnum.rb @@ -12,7 +12,7 @@ class Magnum < Formula def install system "mkdir build" cd "build" do - system "cmake", "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_INSTALL_PREFIX=#{prefix}", "-DWITH_AUDIO=ON", "-DWITH_SDL2APPLICATION=ON", "-DWITH_WINDOWLESSCGLAPPLICATION=ON", "-DWITH_CGLCONTEXT=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", ".." + system "cmake", "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_INSTALL_PREFIX=#{prefix}", "-DWITH_AUDIO=ON", "-DWITH_SDL2APPLICATION=ON", "-DWITH_WINDOWLESSCGLAPPLICATION=ON", "-DWITH_CGLCONTEXT=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_IMAGECONVERTER=ON", "-DWITH_MAGNUMINFO=ON", "-DWITH_AL_INFO=ON", ".." system "cmake", "--build", "." system "cmake", "--build", ".", "--target", "install" end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4d22dc8f2..f4ece4669 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,7 +32,7 @@ endif() # On MSVC remove /W3, as we are replacing it with /W4 if(MSVC) - string(REPLACE "/W3" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif() # Emscripten needs special flag to use WebGL 2 diff --git a/src/Magnum/AbstractFramebuffer.cpp b/src/Magnum/AbstractFramebuffer.cpp index d5ced3a92..68a55540d 100644 --- a/src/Magnum/AbstractFramebuffer.cpp +++ b/src/Magnum/AbstractFramebuffer.cpp @@ -29,8 +29,19 @@ #include "Magnum/BufferImage.h" #endif #include "Magnum/Context.h" +#include "Magnum/CubeMapTexture.h" +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +#include "Magnum/CubeMapTextureArray.h" +#endif #include "Magnum/Extensions.h" #include "Magnum/Image.h" +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/RectangleTexture.h" +#endif +#include "Magnum/Texture.h" +#ifndef MAGNUM_TARGET_GLES2 +#include "Magnum/TextureArray.h" +#endif #include "Implementation/FramebufferState.h" #include "Implementation/State.h" @@ -141,7 +152,7 @@ void AbstractFramebuffer::bindImplementationDefault(FramebufferTarget target) { } else if(target == FramebufferTarget::Draw) { if(state.drawBinding == _id) return; state.drawBinding = _id; - } else CORRADE_ASSERT_UNREACHABLE(); + } else CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ /* Binding the framebuffer finally creates it */ _flags |= ObjectFlag::Created; @@ -229,7 +240,7 @@ void AbstractFramebuffer::blitImplementationANGLE(AbstractFramebuffer& source, A static_cast(destinationRectangle); static_cast(mask); static_cast(filter); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -245,7 +256,7 @@ void AbstractFramebuffer::blitImplementationNV(AbstractFramebuffer& source, Abst static_cast(destinationRectangle); static_cast(mask); static_cast(filter); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -331,6 +342,96 @@ BufferImage2D AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D } #endif +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copyImage(const Range2Di& rectangle, Texture1D& texture, const Int level, const TextureFormat internalFormat) { + CORRADE_ASSERT(rectangle.sizeY() == 1, "AbstractFramebuffer::copyImage(): height must be 1 for 1D textures", ); + bindInternal(FramebufferTarget::Read); + texture.bindInternal(); + glCopyTexImage1D(GL_TEXTURE_1D, level, GLenum(internalFormat), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), 0); +} +#endif + +void AbstractFramebuffer::copyImage(const Range2Di& rectangle, Texture2D& texture, const Int level, const TextureFormat internalFormat) { + bindInternal(FramebufferTarget::Read); + texture.bindInternal(); + glCopyTexImage2D(GL_TEXTURE_2D, level, GLenum(internalFormat), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), 0); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copyImage(const Range2Di& rectangle, RectangleTexture& texture, const TextureFormat internalFormat) { + bindInternal(FramebufferTarget::Read); + texture.bindInternal(); + glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GLenum(internalFormat), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), 0); +} +#endif + +void AbstractFramebuffer::copyImage(const Range2Di& rectangle, CubeMapTexture& texture, const CubeMapCoordinate coordinate, const Int level, const TextureFormat internalFormat) { + bindInternal(FramebufferTarget::Read); + texture.bindInternal(); + glCopyTexImage2D(GLenum(coordinate), level, GLenum(internalFormat), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), 0); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copyImage(const Range2Di& rectangle, Texture1DArray& texture, const Int level, const TextureFormat internalFormat) { + bindInternal(FramebufferTarget::Read); + texture.bindInternal(); + glCopyTexImage2D(GL_TEXTURE_1D_ARRAY, level, GLenum(internalFormat), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), 0); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1D& texture, const Int level, const Int offset) { + CORRADE_ASSERT(rectangle.sizeY() == 1, "AbstractFramebuffer::copyImage(): height must be 1 for 1D textures", ); + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySub1DImplementation(rectangle, texture, level, offset); +} +#endif + +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2D& texture, const Int level, const Vector2i& offset) { + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_2D, level, offset); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, RectangleTexture& texture, const Vector2i& offset) { + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_RECTANGLE, 0, offset); +} +#endif + +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTexture& texture, const Int level, const Vector3i& offset) { + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySubCubeMapImplementation(rectangle, texture, GL_TEXTURE_CUBE_MAP_POSITIVE_X + offset.z(), level, offset.xy()); +} + +#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture3D& texture, const Int level, const Vector3i& offset) { + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1DArray& texture, const Int level, const Vector2i& offset) { + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_1D_ARRAY, level, offset); +} +#endif + +#ifndef MAGNUM_TARGET_GLES2 +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2DArray& texture, const Int level, const Vector3i& offset) { + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); +} +#endif + +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTextureArray& texture, const Int level, const Vector3i& offset) { + bindInternal(FramebufferTarget::Read); + Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); +} +#endif + void AbstractFramebuffer::invalidateImplementationNoOp(GLsizei, const GLenum* const) {} void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, const GLenum* const attachments) { @@ -341,7 +442,7 @@ void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, c #else static_cast(count); static_cast(attachments); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -414,7 +515,7 @@ void AbstractFramebuffer::drawBuffersImplementationEXT(GLsizei count, const GLen #else static_cast(count); static_cast(buffers); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -427,7 +528,7 @@ void AbstractFramebuffer::drawBuffersImplementationNV(GLsizei count, const GLenu #else static_cast(count); static_cast(buffers); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -460,14 +561,14 @@ void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) { glReadBufferNV(buffer); #else static_cast(buffer); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif #ifndef MAGNUM_TARGET_GLES void AbstractFramebuffer::readBufferImplementationDSA(const GLenum buffer) { - glFramebufferReadBufferEXT(_id, buffer); + glNamedFramebufferReadBuffer(_id, buffer); } void AbstractFramebuffer::readBufferImplementationDSAEXT(GLenum buffer) { @@ -492,8 +593,67 @@ void AbstractFramebuffer::readImplementationRobustness(const Range2Di& rectangle static_cast(type); static_cast(dataSize); static_cast(data); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ + #endif +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copySub1DImplementationDefault(const Range2Di& rectangle, AbstractTexture& texture, const Int level, const Int offset) { + texture.bindInternal(); + glCopyTexSubImage1D(texture._target, level, offset, rectangle.min().x(), rectangle.min().y(), rectangle.sizeX()); +} + +void AbstractFramebuffer::copySub1DImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, const Int level, const Int offset) { + glCopyTextureSubImage1D(texture._id, level, offset, rectangle.min().x(), rectangle.min().y(), rectangle.sizeX()); +} + +void AbstractFramebuffer::copySub1DImplementationDSAEXT(const Range2Di& rectangle, AbstractTexture& texture, const Int level, const Int offset) { + texture._flags |= ObjectFlag::Created; + glCopyTextureSubImage1DEXT(texture._id, texture._target, level, offset, rectangle.min().x(), rectangle.min().y(), rectangle.sizeX()); +} +#endif + +void AbstractFramebuffer::copySub2DImplementationDefault(const Range2Di& rectangle, AbstractTexture& texture, const GLenum target, const Int level, const Vector2i& offset) { + texture.bindInternal(); + glCopyTexSubImage2D(target, level, offset.x(), offset.y(), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY()); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copySub2DImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, const GLenum, const Int level, const Vector2i& offset) { + glCopyTextureSubImage2D(texture._id, level, offset.x(), offset.y(), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY()); +} + +void AbstractFramebuffer::copySubCubeMapImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, const GLenum target, const Int level, const Vector2i& offset) { + glCopyTextureSubImage3D(texture._id, level, offset.x(), offset.y(), target - GL_TEXTURE_CUBE_MAP_POSITIVE_X, rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY()); +} + +void AbstractFramebuffer::copySub2DImplementationDSAEXT(const Range2Di& rectangle, AbstractTexture& texture, const GLenum target, const Int level, const Vector2i& offset) { + texture._flags |= ObjectFlag::Created; + glCopyTextureSubImage2DEXT(texture._id, target, level, offset.x(), offset.y(), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY()); +} +#endif + +#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) +void AbstractFramebuffer::copySub3DImplementationDefault(const Range2Di& rectangle, AbstractTexture& texture, const Int level, const Vector3i& offset) { + texture.bindInternal(); + #ifndef MAGNUM_TARGET_GLES2 + glCopyTexSubImage3D + #else + glCopyTexSubImage3DOES #endif + (texture._target, level, offset.x(), offset.y(), offset.z(), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY()); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::copySub3DImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, const Int level, const Vector3i& offset) { + glCopyTextureSubImage3D(texture._id, level, offset.x(), offset.y(), offset.z(), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY()); +} + +void AbstractFramebuffer::copySub3DImplementationDSAEXT(const Range2Di& rectangle, AbstractTexture& texture, const Int level, const Vector3i& offset) { + texture._flags |= ObjectFlag::Created; + glCopyTextureSubImage3DEXT(texture._id, texture._target, level, offset.x(), offset.y(), offset.z(), rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY()); } #endif diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index d8c9a61fc..41d048eab 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -319,8 +319,8 @@ class MAGNUM_EXPORT AbstractFramebuffer { * * If @extension{ARB,robustness} is available, the operation is * protected from buffer overflow. - * @see @fn_gl{BindFramebuffer}, @fn_gl{ReadPixels} or - * @fn_gl_extension{ReadnPixels,ARB,robustness} + * @see @fn_gl{BindFramebuffer}, then @fn_gl{PixelStore} and + * @fn_gl{ReadPixels} or @fn_gl_extension{ReadnPixels,ARB,robustness} */ void read(const Range2Di& rectangle, Image2D& image); @@ -383,6 +383,307 @@ class MAGNUM_EXPORT AbstractFramebuffer { #endif #endif + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Copy block of pixels from framebuffer to 1D texture image + * @param rectangle Framebuffer rectangle to copy. Height must + * be `1`. + * @param texture Texture where to put the data + * @param level Texture mip level + * @param internalFormat Texture internal format + * + * On platforms that support it prefer to use @ref Texture1D::setStorage() + * and @ref copySubImage() instead, as it avoids unnecessary + * reallocations and has better performance characteristics. This call + * also has no equivalent in @extension{ARB,direct_state_access}, thus + * the texture needs to be bound to some texture unit before the + * operation. + * @see @ref Texture1D::maxSize(), @fn_gl{BindFramebuffer}, then + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexImage1D} + * @requires_gl 1D textures are not available in OpenGL ES or WebGL. + * @deprecated_gl Prefer to use @ref Texture1D::setStorage() and + * @ref copySubImage() instead. + */ + void copyImage(const Range2Di& rectangle, Texture1D& texture, Int level, TextureFormat internalFormat); + #endif + + /** + * @brief Copy block of pixels from framebuffer to 2D texture image + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param internalFormat Texture internal format + * + * On platforms that support it prefer to use @ref Texture2D::setStorage() + * and @ref copySubImage() instead, as it avoids unnecessary + * reallocations and has better performance characteristics. This call + * also has no equivalent in @extension{ARB,direct_state_access}, thus + * the texture needs to be bound to some texture unit before the + * operation. + * @see @ref Texture2D::maxSize(), @fn_gl{BindFramebuffer}, then + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexImage2D} + * @deprecated_gl Prefer to use @ref Texture2D::setStorage() and + * @ref copySubImage() instead. + */ + void copyImage(const Range2Di& rectangle, Texture2D& texture, Int level, TextureFormat internalFormat); + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Copy block of pixels from framebuffer to rectangle texture + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param internalFormat Texture internal format + * + * On platforms that support it prefer to use @ref RectangleTexture::setStorage() + * and @ref copySubImage() instead, as it avoids unnecessary + * reallocations and has better performance characteristics. This call + * also has no equivalent in @extension{ARB,direct_state_access}, thus + * the texture needs to be bound to some texture unit before the + * operation. + * @see @ref Texture2D::maxSize(), @fn_gl{BindFramebuffer}, then + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexImage2D} + * @requires_gl31 Extension @extension{ARB,texture_rectangle} + * @requires_gl Rectangle textures are not available in OpenGL ES and + * WebGL. + * @deprecated_gl Prefer to use @ref RectangleTexture::setStorage() and + * @ref copySubImage() instead. + */ + void copyImage(const Range2Di& rectangle, RectangleTexture& texture, TextureFormat internalFormat); + #endif + + /** + * @brief Copy block of pixels from framebuffer to cube map texture image + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param coordinate Cube map coordinate + * @param internalFormat Texture internal format + * + * On platforms that support it prefer to use @ref CubeMapTexture::setStorage() + * and @ref copySubImage() instead, as it avoids unnecessary + * reallocations and has better performance characteristics. This call + * also has no equivalent in @extension{ARB,direct_state_access}, thus + * the texture needs to be bound to some texture unit before the + * operation. + * @see @ref Texture2D::maxSize(), @fn_gl{BindFramebuffer}, then + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexImage2D} + * @deprecated_gl Prefer to use @ref CubeMapTexture::setStorage() and + * @ref copySubImage() instead. + */ + void copyImage(const Range2Di& rectangle, CubeMapTexture& texture, CubeMapCoordinate coordinate, Int level, TextureFormat internalFormat); + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Copy block of pixels from framebuffer to 1D texture array image + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param internalFormat Texture internal format + * + * On platforms that support it prefer to use @ref Texture2D::setStorage() + * and @ref copySubImage() instead, as it avoids unnecessary + * reallocations and has better performance characteristics. This call + * also has no equivalent in @extension{ARB,direct_state_access}, thus + * the texture needs to be bound to some texture unit before the + * operation. + * @see @ref Texture2D::maxSize(), @fn_gl{BindFramebuffer}, then + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexImage2D} + * @requires_gl 1D array textures are not available in OpenGL ES or + * WebGL, only 2D ones. + * @deprecated_gl Prefer to use @ref Texture1DArray::setStorage() and + * @ref copySubImage() instead. + */ + void copyImage(const Range2Di& rectangle, Texture1DArray& texture, Int level, TextureFormat internalFormat); + #endif + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Copy block of pixels from framebuffer to 1D texture subimage + * @param rectangle Framebuffer rectangle to copy. Height must + * be `1`. + * @param texture Texture where to put the data + * @param level Texture mip level + * @param offset Offset inside the texture + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref Texture1D::setStorage(), @fn_gl{BindFramebuffer}, then + * @fn_gl2{CopyTextureSubImage1D,CopyTexSubImage1D}, + * @fn_gl_extension{CopyTextureSubImage1D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage1D} + * @requires_gl 1D textures are not available in OpenGL ES or WebGL. + */ + void copySubImage(const Range2Di& rectangle, Texture1D& texture, Int level, Int offset); + #endif + + /** + * @brief Copy block of pixels from framebuffer to 2D texture subimage + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param offset Offset inside the texture + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref Texture2D::setStorage(), @fn_gl{BindFramebuffer}, then + * @fn_gl2{CopyTextureSubImage2D,CopyTexSubImage2D}, + * @fn_gl_extension{CopyTextureSubImage2D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage2D} + */ + void copySubImage(const Range2Di& rectangle, Texture2D& texture, Int level, const Vector2i& offset); + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Copy block of pixels from framebuffer to rectangle texture subimage + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param offset Offset inside the texture + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref RectangleTexture::setStorage(), @fn_gl{BindFramebuffer}, + * then @fn_gl2{CopyTextureSubImage2D,CopyTexSubImage2D}, + * @fn_gl_extension{CopyTextureSubImage2D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage2D} + * @requires_gl Rectangle textures are not available in OpenGL ES and + * WebGL. + */ + void copySubImage(const Range2Di& rectangle, RectangleTexture& texture, const Vector2i& offset); + #endif + + /** + * @brief Copy block of pixels from framebuffer to cube map texture subimage + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param offset Offset inside the texture + * + * Z coordinate of the offset is equivalent to number of texture face, + * i.e. +X is `0` and so on, in order of (+X, -X, +Y, -Y, +Z, -Z). If + * neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) nor + * @extension{EXT,direct_state_access} desktop extension is available, + * the texture is bound before the operation (if not already). + * @see @ref CubeMapTexture::setStorage(), @fn_gl{BindFramebuffer}, + * then @fn_gl2{CopyTextureSubImage3D,CopyTexSubImage3D}, + * @fn_gl_extension{CopyTextureSubImage2D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage2D} + */ + void copySubImage(const Range2Di& rectangle, CubeMapTexture& texture, Int level, const Vector3i& offset); + + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + /** + * @brief Copy block of pixels from framebuffer to 3D texture subimage + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param offset Offset inside the texture + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref Texture3D::setStorage(), @fn_gl{BindFramebuffer}, then + * @fn_gl2{CopyTextureSubImage3D,CopyTexSubImage3D}, + * @fn_gl_extension{CopyTextureSubImage3D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage3D} + * @requires_gles30 Extension @es_extension{OES,texture_3D} in OpenGL + * ES 2.0. + * @requires_webgl20 Only 2D textures are available in WebGL 1.0. + */ + void copySubImage(const Range2Di& rectangle, Texture3D& texture, Int level, const Vector3i& offset); + #endif + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Copy block of pixels from framebuffer to 1D texture array subimage + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param offset Offset inside the texture + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref Texture1DArray::setStorage(), @fn_gl{BindFramebuffer}, + * then @fn_gl2{CopyTextureSubImage2D,CopyTexSubImage2D}, + * @fn_gl_extension{CopyTextureSubImage2D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage2D} + * @requires_gl 1D array textures are not available in OpenGL ES or + * WebGL, only 2D ones. + */ + void copySubImage(const Range2Di& rectangle, Texture1DArray& texture, Int level, const Vector2i& offset); + #endif + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Copy block of pixels from framebuffer to 2D texture array subimage + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param offset Offset inside the texture + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref Texture2DArray::setStorage(), @fn_gl{BindFramebuffer}, + * then @fn_gl2{CopyTextureSubImage3D,CopyTexSubImage3D}, + * @fn_gl_extension{CopyTextureSubImage3D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage3D} + * @requires_gl30 Extension @extension{EXT,texture_array} + * @requires_gles30 Array textures are not available in OpenGL ES 2.0. + * @requires_webgl20 Array textures are not available in WebGL 1.0. + */ + void copySubImage(const Range2Di& rectangle, Texture2DArray& texture, Int level, const Vector3i& offset); + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * @brief Copy block of pixels from framebuffer to cube map texture array subimage + * @param rectangle Framebuffer rectangle to copy + * @param texture Texture where to put the data + * @param level Texture mip level + * @param offset Offset inside the texture + * + * Z coordinate of the offset is equivalent to layer * 6 + number of + * texture face, i.e. +X is `0` and so on, in order of (+X, -X, +Y, -Y, + * +Z, -Z). If neither @extension{ARB,direct_state_access} (part of + * OpenGL 4.5) nor @extension{EXT,direct_state_access} desktop + * available, the texture is bound before the operation (if not + * already). + * @see @ref CubeMapTextureArray::setStorage(), @fn_gl{BindFramebuffer}, + * then @fn_gl2{CopyTextureSubImage3D,CopyTexSubImage3D}, + * @fn_gl_extension{CopyTextureSubImage3D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CopyTexSubImage3D} + * @requires_gl40 Extension @extension{ARB,texture_cube_map_array} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/ + * @es_extension{EXT,texture_cube_map_array} + * @requires_gles Cube map texture arrays are not available in WebGL. + */ + void copySubImage(const Range2Di& rectangle, CubeMapTextureArray& texture, Int level, const Vector3i& offset); + #endif + #ifdef DOXYGEN_GENERATING_OUTPUT private: #else @@ -462,6 +763,27 @@ class MAGNUM_EXPORT AbstractFramebuffer { static void MAGNUM_LOCAL readImplementationRobustness(const Range2Di& rectangle, PixelFormat format, PixelType type, std::size_t dataSize, GLvoid* data); #endif + #ifndef MAGNUM_TARGET_GLES + static void MAGNUM_LOCAL copySub1DImplementationDefault(const Range2Di& rectangle, AbstractTexture& texture, Int level, Int offset); + static void MAGNUM_LOCAL copySub1DImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, Int level, Int offset); + static void MAGNUM_LOCAL copySub1DImplementationDSAEXT(const Range2Di& rectangle, AbstractTexture& texture, Int level, Int offset); + #endif + + static void MAGNUM_LOCAL copySub2DImplementationDefault(const Range2Di& rectangle, AbstractTexture& texture, GLenum textureTarget, Int level, const Vector2i& offset); + #ifndef MAGNUM_TARGET_GLES + static void MAGNUM_LOCAL copySub2DImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, GLenum textureTarget, Int level, const Vector2i& offset); + static void MAGNUM_LOCAL copySubCubeMapImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, GLenum textureTarget, Int level, const Vector2i& offset); + static void MAGNUM_LOCAL copySub2DImplementationDSAEXT(const Range2Di& rectangle, AbstractTexture& texture, GLenum textureTarget, Int level, const Vector2i& offset); + #endif + + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + static void MAGNUM_LOCAL copySub3DImplementationDefault(const Range2Di& rectangle, AbstractTexture& texture, Int level, const Vector3i& offset); + #endif + #ifndef MAGNUM_TARGET_GLES + static void MAGNUM_LOCAL copySub3DImplementationDSA(const Range2Di& rectangle, AbstractTexture& texture, Int level, const Vector3i& offset); + static void MAGNUM_LOCAL copySub3DImplementationDSAEXT(const Range2Di& rectangle, AbstractTexture& texture, Int level, const Vector3i& offset); + #endif + void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*); void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/AbstractObject.cpp b/src/Magnum/AbstractObject.cpp index beaff5bca..24ac34c7a 100644 --- a/src/Magnum/AbstractObject.cpp +++ b/src/Magnum/AbstractObject.cpp @@ -107,7 +107,7 @@ namespace { return khrIdentifier; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } } #endif @@ -140,7 +140,7 @@ void AbstractObject::labelImplementationKhr(const GLenum identifier, const GLuin static_cast(identifier); static_cast(name); static_cast(label); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -152,7 +152,7 @@ void AbstractObject::labelImplementationExt(const GLenum identifier, const GLuin static_cast(identifier); static_cast(name); static_cast(label); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -169,7 +169,7 @@ std::string AbstractObject::getLabelImplementationKhr(const GLenum identifier, c #else static_cast(identifier); static_cast(name); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif /* Make place also for the null terminator */ @@ -180,7 +180,7 @@ std::string AbstractObject::getLabelImplementationKhr(const GLenum identifier, c #elif !defined(CORRADE_TARGET_NACL) glGetObjectLabelKHR(identifier, name, size+1, nullptr, &label[0]); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif /* Pop null terminator and return the string */ @@ -198,7 +198,7 @@ std::string AbstractObject::getLabelImplementationExt(const GLenum identifier, c #else static_cast(identifier); static_cast(name); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif /* Make place also for the null terminator */ @@ -207,7 +207,7 @@ std::string AbstractObject::getLabelImplementationExt(const GLenum identifier, c #ifndef CORRADE_TARGET_NACL glGetObjectLabelEXT(type, name, size+1, nullptr, &label[0]); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif /* Pop null terminator and return the string */ diff --git a/src/Magnum/AbstractQuery.cpp b/src/Magnum/AbstractQuery.cpp index 4f90c7fd8..c4beefffe 100644 --- a/src/Magnum/AbstractQuery.cpp +++ b/src/Magnum/AbstractQuery.cpp @@ -55,7 +55,7 @@ AbstractQuery::~AbstractQuery() { #elif !defined(CORRADE_TARGET_EMSCRIPTEN) glDeleteQueriesEXT(1, &_id); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif _flags |= ObjectFlag::Created; } @@ -66,7 +66,7 @@ void AbstractQuery::createImplementationDefault() { #elif !defined(CORRADE_TARGET_EMSCRIPTEN) glGenQueriesEXT(1, &_id); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -126,7 +126,7 @@ template<> Int AbstractQuery::result() { #elif !defined(CORRADE_TARGET_NACL) glGetQueryObjectivEXT(_id, GL_QUERY_RESULT_EXT, &result); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif return result; } @@ -138,7 +138,7 @@ template<> UnsignedLong AbstractQuery::result() { #elif !defined(CORRADE_TARGET_NACL) glGetQueryObjectui64vEXT(_id, GL_QUERY_RESULT_EXT, &result); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif return result; } @@ -150,7 +150,7 @@ template<> Long AbstractQuery::result() { #elif !defined(CORRADE_TARGET_NACL) glGetQueryObjecti64vEXT(_id, GL_QUERY_RESULT_EXT, &result); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif return result; } diff --git a/src/Magnum/AbstractQuery.h b/src/Magnum/AbstractQuery.h index ea2b20e86..0828a52a4 100644 --- a/src/Magnum/AbstractQuery.h +++ b/src/Magnum/AbstractQuery.h @@ -136,11 +136,10 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { * See @ref resultAvailable(). * @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT} * @requires_gl33 Extension @extension{ARB,timer_query} for result - * type @ref Magnum::UnsignedInt "UnsignedInt" and @ref Magnum::Long - * "Long" + * type @ref Magnum::UnsignedLong "UnsignedLong" and @ref Magnum::Long "Long" * @requires_es_extension Extension @es_extension{EXT,disjoint_timer_query} * for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong" - * @ref Magnum::Long "Long". + * and @ref Magnum::Long "Long". * @requires_gles Only @ref Magnum::UnsignedInt "UnsignedInt" result * type is available in WebGL. */ @@ -184,6 +183,9 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { void begin(GLenum target); #endif + GLuint _id; + GLenum _target; + private: #ifndef MAGNUM_TARGET_WEBGL AbstractQuery& setLabelInternal(Containers::ArrayView label); @@ -194,8 +196,6 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { void MAGNUM_LOCAL createImplementationDSA(); #endif - GLuint _id; - GLenum _target; ObjectFlags _flags; }; diff --git a/src/Magnum/AbstractShaderProgram.cpp b/src/Magnum/AbstractShaderProgram.cpp index fc5f2f096..ce19cb1a6 100644 --- a/src/Magnum/AbstractShaderProgram.cpp +++ b/src/Magnum/AbstractShaderProgram.cpp @@ -368,6 +368,10 @@ void AbstractShaderProgram::bindFragmentDataLocationIndexedInternal(const Unsign #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setTransformFeedbackOutputs(const std::initializer_list outputs, const TransformFeedbackBufferMode bufferMode) { + (this->*Context::current().state().shaderProgram->transformFeedbackVaryingsImplementation)({outputs.begin(), outputs.size()}, bufferMode); +} + +void AbstractShaderProgram::transformFeedbackVaryingsImplementationDefault(const Containers::ArrayView outputs, const TransformFeedbackBufferMode bufferMode) { /** @todo VLAs */ Containers::Array names{outputs.size()}; @@ -376,6 +380,19 @@ void AbstractShaderProgram::setTransformFeedbackOutputs(const std::initializer_l glTransformFeedbackVaryings(_id, outputs.size(), names, GLenum(bufferMode)); } + +#ifdef CORRADE_TARGET_WINDOWS +void AbstractShaderProgram::transformFeedbackVaryingsImplementationDanglingWorkaround(const Containers::ArrayView outputs, const TransformFeedbackBufferMode bufferMode) { + /* NVidia on Windows doesn't copy the names when calling + glTransformFeedbackVaryings() so it then fails at link time because the + char* are dangling. We have to do the copy on the engine side and keep + the values until link time (which can happen any time and multiple + times, so basically for the remaining lifetime of the shader program) */ + _transformFeedbackVaryingNames.assign(outputs.begin(), outputs.end()); + + transformFeedbackVaryingsImplementationDefault({_transformFeedbackVaryingNames.data(), _transformFeedbackVaryingNames.size()}, bufferMode); +} +#endif #endif bool AbstractShaderProgram::link(std::initializer_list> shaders) { @@ -478,7 +495,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -506,7 +523,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -534,7 +551,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -562,7 +579,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -590,7 +607,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -618,7 +635,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -646,7 +663,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -674,7 +691,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -850,7 +867,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -878,7 +895,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -906,7 +923,7 @@ void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint locat static_cast(location); static_cast(count); static_cast(values); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 74538e0b9..9c5aed167 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -36,6 +36,10 @@ #include "Magnum/AbstractObject.h" #include "Magnum/Attribute.h" +#if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES2) +#include +#endif + namespace Magnum { namespace Implementation { struct ShaderProgramState; } @@ -1189,6 +1193,13 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { Int uniformLocationInternal(Containers::ArrayView name); UnsignedInt uniformBlockIndexInternal(Containers::ArrayView name); + #ifndef MAGNUM_TARGET_GLES2 + void MAGNUM_LOCAL transformFeedbackVaryingsImplementationDefault(Containers::ArrayView outputs, TransformFeedbackBufferMode bufferMode); + #ifdef CORRADE_TARGET_WINDOWS + void MAGNUM_LOCAL transformFeedbackVaryingsImplementationDanglingWorkaround(Containers::ArrayView outputs, TransformFeedbackBufferMode bufferMode); + #endif + #endif + #ifndef MAGNUM_BUILD_DEPRECATED void use(); #endif @@ -1347,6 +1358,12 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { #endif GLuint _id; + + #if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES2) + /* Needed for the nv-windows-dangling-transform-feedback-varying-names + workaround */ + std::vector _transformFeedbackVaryingNames; + #endif }; } diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 815c029ef..e3f3dad94 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -808,7 +808,7 @@ PixelFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in return PixelFormat::DepthStencil; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } PixelType AbstractTexture::imageTypeForInternalFormat(const TextureFormat internalFormat) { @@ -1053,7 +1053,7 @@ PixelType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern #endif } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } #endif @@ -1254,7 +1254,7 @@ void AbstractTexture::storageImplementationFallback(const GLsizei levels, const #endif /* No other targets are available */ - } else CORRADE_ASSERT_UNREACHABLE(); + } else CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } #endif @@ -1269,7 +1269,7 @@ void AbstractTexture::storageImplementationDefault(GLsizei levels, TextureFormat static_cast(levels); static_cast(internalFormat); static_cast(size); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -1313,7 +1313,7 @@ void AbstractTexture::storageImplementationFallback(GLsizei levels, TextureForma #endif /* No other targets are available */ - else CORRADE_ASSERT_UNREACHABLE(); + else CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } #endif @@ -1328,7 +1328,7 @@ void AbstractTexture::storageImplementationDefault(GLsizei levels, TextureFormat static_cast(levels); static_cast(internalFormat); static_cast(size); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -1511,7 +1511,7 @@ void AbstractTexture::subImageImplementationDefault(GLint level, const Vector3i& static_cast(format); static_cast(type); static_cast(data); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -1527,7 +1527,7 @@ void AbstractTexture::compressedSubImageImplementationDefault(const GLint level, static_cast(size); static_cast(format); static_cast(data); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -1995,7 +1995,7 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL static_cast(level); static_cast(internalFormat); static_cast(image); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -2016,7 +2016,7 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture #else static_cast(level); static_cast(image); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 77694e01f..4d49b9540 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -133,6 +133,7 @@ functions do nothing. */ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { friend Implementation::TextureState; + friend AbstractFramebuffer; friend CubeMapTexture; public: diff --git a/src/Magnum/Attribute.cpp b/src/Magnum/Attribute.cpp index c3af6c051..10c2f5c0e 100644 --- a/src/Magnum/Attribute.cpp +++ b/src/Magnum/Attribute.cpp @@ -49,7 +49,7 @@ UnsignedInt FloatAttribute::size(GLint components, DataType dataType) { #endif } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } #ifndef MAGNUM_TARGET_GLES2 @@ -66,7 +66,7 @@ UnsignedInt IntAttribute::size(GLint components, DataType dataType) { return 4*components; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } #endif @@ -77,7 +77,7 @@ UnsignedInt DoubleAttribute::size(GLint components, DataType dataType) { return 8*components; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } #endif @@ -103,7 +103,7 @@ UnsignedInt Attribute>::size(GLint components, DataType d #endif } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } UnsignedInt Attribute>::size(GLint components, DataType dataType) { @@ -136,44 +136,51 @@ UnsignedInt Attribute>::size(GLint components, DataType d #endif } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } Debug& operator<<(Debug& debug, SizedAttribute<1, 1>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case SizedAttribute<1, 1>::Components::One: return debug << "Attribute::Components::One"; + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, SizedAttribute<1, 2>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case SizedAttribute<1, 2>::Components::One: return debug << "Attribute::Components::One"; case SizedAttribute<1, 2>::Components::Two: return debug << "Attribute::Components::Two"; + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, SizedAttribute<1, 3>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case SizedAttribute<1, 3>::Components::One: return debug << "Attribute::Components::One"; case SizedAttribute<1, 3>::Components::Two: return debug << "Attribute::Components::Two"; case SizedAttribute<1, 3>::Components::Three: return debug << "Attribute::Components::Three"; + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, SizedAttribute<1, 4>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case SizedAttribute<1, 4>::Components::One: return debug << "Attribute::Components::One"; case SizedAttribute<1, 4>::Components::Two: @@ -182,40 +189,48 @@ Debug& operator<<(Debug& debug, SizedAttribute<1, 4>::Components value) { return debug << "Attribute::Components::Three"; case SizedAttribute<1, 4>::Components::Four: return debug << "Attribute::Components::Four"; + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, SizedMatrixAttribute<2>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case SizedMatrixAttribute<2>::Components::Two: return debug << "Attribute::Components::Two"; + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, SizedMatrixAttribute<3>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case SizedMatrixAttribute<3>::Components::Three: return debug << "Attribute::Components::Three"; + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, SizedMatrixAttribute<4>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case SizedMatrixAttribute<4>::Components::Four: return debug << "Attribute::Components::Four"; + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, Attribute>::Components value) { switch(value) { + /* LCOV_EXCL_START */ case Attribute>::Components::One: return debug << "Attribute::Components::One"; case Attribute>::Components::Two: @@ -228,13 +243,15 @@ Debug& operator<<(Debug& debug, Attribute>::Components va case Attribute>::Components::BGRA: return debug << "Attribute::Components::BGRA"; #endif + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::Components::(invalid)"; + return debug << "Attribute::Components(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, FloatAttribute::DataType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case FloatAttribute::DataType::value: return debug << "Attribute::DataType::" #value; _c(UnsignedByte) _c(Byte) @@ -248,14 +265,16 @@ Debug& operator<<(Debug& debug, FloatAttribute::DataType value) { _c(Double) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::DataType::(invalid)"; + return debug << "Attribute::DataType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #ifndef MAGNUM_TARGET_GLES2 Debug& operator<<(Debug& debug, IntAttribute::DataType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case IntAttribute::DataType::value: return debug << "Attribute::DataType::" #value; _c(UnsignedByte) _c(Byte) @@ -264,26 +283,30 @@ Debug& operator<<(Debug& debug, IntAttribute::DataType value) { _c(UnsignedInt) _c(Int) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::DataType::(invalid)"; + return debug << "Attribute::DataType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif #ifndef MAGNUM_TARGET_GLES Debug& operator<<(Debug& debug, DoubleAttribute::DataType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case DoubleAttribute::DataType::value: return debug << "Attribute::DataType::" #value; _c(Double) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::DataType::(invalid)"; + return debug << "Attribute::DataType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif Debug& operator<<(Debug& debug, Attribute>::DataType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Attribute>::DataType::value: return debug << "Attribute::DataType::" #value; _c(UnsignedByte) _c(Byte) @@ -298,13 +321,15 @@ Debug& operator<<(Debug& debug, Attribute>::DataType valu _c(UnsignedInt10f11f11fRev) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::DataType::(invalid)"; + return debug << "Attribute::DataType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, Attribute>::DataType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Attribute>::DataType::value: return debug << "Attribute::DataType::" #value; _c(UnsignedByte) _c(Byte) @@ -322,9 +347,10 @@ Debug& operator<<(Debug& debug, Attribute>::DataType valu _c(Int2101010Rev) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Attribute::DataType::(invalid)"; + return debug << "Attribute::DataType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } }} diff --git a/src/Magnum/Attribute.h b/src/Magnum/Attribute.h index 3645826e8..439e81383 100644 --- a/src/Magnum/Attribute.h +++ b/src/Magnum/Attribute.h @@ -171,7 +171,11 @@ template class Attribute { * @requires_webgl20 Half float vertex attributes are not available * in WebGL 1.0. */ + #ifndef MAGNUM_TARGET_GLES2 HalfFloat = GL_HALF_FLOAT, + #else + HalfFloat = GL_HALF_FLOAT_OES, + #endif #endif /** Float. Only for float attribute types. */ diff --git a/src/Magnum/Audio/AbstractImporter.h b/src/Magnum/Audio/AbstractImporter.h index 13daf32dd..3d6b9ef1f 100644 --- a/src/Magnum/Audio/AbstractImporter.h +++ b/src/Magnum/Audio/AbstractImporter.h @@ -61,6 +61,11 @@ checked by the implementation: there is any file opened. Plugin interface string is `"cz.mosra.magnum.Audio.AbstractImporter/0.1"`. + +@attention @ref Corrade::Containers::Array instances returned from the plugin + should *not* use anything else than the default deleter, otherwise this can + cause dangling function pointer call on array destruction if the plugin + gets unloaded before the array is destroyed. */ class MAGNUM_AUDIO_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlugin { CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Audio.AbstractImporter/0.1") diff --git a/src/Magnum/Audio/Audio.cpp b/src/Magnum/Audio/Audio.cpp index 4384c776f..c4c040c21 100644 --- a/src/Magnum/Audio/Audio.cpp +++ b/src/Magnum/Audio/Audio.cpp @@ -33,21 +33,16 @@ namespace Magnum { namespace Audio { /* Verify types */ static_assert(std::is_same::value, "ALubyte is not the same as UnsignedByte"); -/** @todo Why `ALbyte` is defined as `char` and not `signed char` on OSX? */ -#ifndef CORRADE_TARGET_APPLE -static_assert(std::is_same::value, "ALbyte is not the same as Byte"); -#else -static_assert(std::is_signed::value && sizeof(ALbyte) == 1, "ALbyte does not have the same characteristics as Byte"); -#endif +/* ALbyte is defined as `signed char` in OpenAL Soft and `char` in the official + SDK from Creative and on Apple. Both are okay. */ +static_assert(std::is_same::value || (std::is_signed::value && sizeof(ALbyte) == 1), "ALbyte does not have the characteristics as Byte"); static_assert(std::is_same::value, "ALushort is not the same as UnsignedShort"); static_assert(std::is_same::value, "ALshort is not the same as Short"); static_assert(std::is_same::value, "ALuint is not the same as UnsignedInt"); static_assert(std::is_same::value, "ALint is not the same as Int"); static_assert(std::is_same::value, "ALsizei is not the same as Int"); static_assert(std::is_same::value, "ALfloat is not the same as Float"); -#ifndef MAGNUM_TARGET_GLES static_assert(std::is_same::value, "ALdouble is not the same as Double"); -#endif /* Verify boolean values */ static_assert(AL_FALSE == false, "AL_FALSE is not the same as false"); diff --git a/src/Magnum/Audio/Buffer.cpp b/src/Magnum/Audio/Buffer.cpp index cc1f00cde..705e406ab 100644 --- a/src/Magnum/Audio/Buffer.cpp +++ b/src/Magnum/Audio/Buffer.cpp @@ -31,20 +31,49 @@ namespace Magnum { namespace Audio { Debug& operator<<(Debug& debug, const Buffer::Format value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Buffer::Format::value: return debug << "Audio::Buffer::Format::" #value; _c(Mono8) _c(Mono16) _c(Stereo8) _c(Stereo16) + _c(MonoALaw) + _c(StereoALaw) + + _c(MonoMuLaw) + _c(StereoMuLaw) + _c(MonoFloat) _c(StereoFloat) _c(MonoDouble) _c(StereoDouble) + + _c(Quad8) + _c(Quad16) + _c(Quad32) + + _c(Rear8) + _c(Rear16) + _c(Rear32) + + _c(Surround51Channel8) + _c(Surround51Channel16) + _c(Surround51Channel32) + + _c(Surround61Channel8) + _c(Surround61Channel16) + _c(Surround61Channel32) + + _c(Surround71Channel8) + _c(Surround71Channel16) + _c(Surround71Channel32) + #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Audio::Buffer::Format::(invalid)"; + return debug << "Audio::Buffer::Format(" << Debug::nospace << reinterpret_cast(ALenum(value)) << Debug::nospace << ")"; } }} diff --git a/src/Magnum/Audio/Buffer.h b/src/Magnum/Audio/Buffer.h index fec59322f..fa0ddf3fe 100644 --- a/src/Magnum/Audio/Buffer.h +++ b/src/Magnum/Audio/Buffer.h @@ -55,7 +55,35 @@ class Buffer { Mono8 = AL_FORMAT_MONO8, /**< 8-bit unsigned mono */ Mono16 = AL_FORMAT_MONO16, /**< 16-bit signed mono */ Stereo8 = AL_FORMAT_STEREO8, /**< 8-bit interleaved unsigned stereo */ - Stereo16 = AL_FORMAT_STEREO16, /**< 16-bit interleaved signed stereo */ + Stereo16 = AL_FORMAT_STEREO16, /**< 16-bit interleaved signed stereo */ + + /** + * @brief 8-bit mono [A-Law Compressed Sound Format](https://en.wikipedia.org/wiki/A-law_algorithm) + * + * @requires_al_extension Extension @al_extension{EXT,ALAW} + */ + MonoALaw = AL_FORMAT_MONO_ALAW_EXT, + + /** + * @brief 8-bit interleaved stereo [A-Law Compressed Sound Format](https://en.wikipedia.org/wiki/A-law_algorithm) + * + * @requires_al_extension Extension @al_extension{EXT,ALAW} + */ + StereoALaw = AL_FORMAT_STEREO_ALAW_EXT, + + /** + * @brief 8-bit mono [μ-Law Compressed Sound Format](https://en.wikipedia.org/wiki/Μ-law_algorithm) + * + * @requires_al_extension Extension @al_extension{EXT,MULAW} + */ + MonoMuLaw = AL_FORMAT_MONO_MULAW_EXT, + + /** + * @brief 8-bit interleaved [μ-Law Compressed Sound Format](https://en.wikipedia.org/wiki/Μ-law_algorithm) + * + * @requires_al_extension Extension @al_extension{EXT,MULAW} + */ + StereoMuLaw = AL_FORMAT_STEREO_MULAW_EXT, /** * @brief 32-bit floating-point mono @@ -83,7 +111,112 @@ class Buffer { * * @requires_al_extension Extension @al_extension{EXT,double} */ - StereoDouble = AL_FORMAT_STEREO_DOUBLE_EXT + StereoDouble = AL_FORMAT_STEREO_DOUBLE_EXT, + + /** + * @brief 8-bit unsigned quadrophonic + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Quad8 = AL_FORMAT_QUAD8, + + /** + * @brief 16-bit signed quadrophonic + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Quad16 = AL_FORMAT_QUAD16, + + /** + * @brief 32-bit interleaved floating-point quadrophonic + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Quad32 = AL_FORMAT_QUAD32, + + /** + * @brief 8-bit unsigned rear + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Rear8 = AL_FORMAT_REAR8, + + /** + * @brief 16-bit signed rear + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Rear16 = AL_FORMAT_REAR16, + + /** + * @brief 32-bit interleaved floating-point rear + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Rear32 = AL_FORMAT_REAR32, + + /** + * @brief 8-bit unsigned 5.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround51Channel8 = AL_FORMAT_51CHN8, + + /** + * @brief 16-bit signed 5.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround51Channel16 = AL_FORMAT_51CHN16, + + /** + * @brief 32-bit interleaved floating-point 5.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround51Channel32 = AL_FORMAT_51CHN32, + + /** + * @brief 8-bit unsigned 6.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround61Channel8 = AL_FORMAT_61CHN8, + + /** + * @brief 16-bit signed 6.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround61Channel16 = AL_FORMAT_61CHN16, + + /** + * @brief 32-bit interleaved floating-point 6.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround61Channel32 = AL_FORMAT_61CHN32, + + /** + * @brief 8-bit unsigned 7.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround71Channel8 = AL_FORMAT_71CHN8, + + /** + * @brief 16-bit signed 7.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround71Channel16 = AL_FORMAT_71CHN16, + + /** + * @brief 32-bit interleaved floating-point 7.1 surround + * + * @requires_al_extension Extension @al_extension{EXT,MCFORMATS} + */ + Surround71Channel32 = AL_FORMAT_71CHN32 }; /** diff --git a/src/Magnum/Audio/CMakeLists.txt b/src/Magnum/Audio/CMakeLists.txt index 1a156e3ff..0607c8d2b 100644 --- a/src/Magnum/Audio/CMakeLists.txt +++ b/src/Magnum/Audio/CMakeLists.txt @@ -74,9 +74,25 @@ install(TARGETS MagnumAudio ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(FILES ${MagnumAudio_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Audio) +# Magnum Audio target alias for superprojects +add_library(Magnum::Audio ALIAS MagnumAudio) + +if(WITH_AL_INFO) + add_executable(magnum-al-info magnum-al-info.cpp) + target_link_libraries(magnum-al-info MagnumAudio) + install(TARGETS magnum-al-info DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}) + + if(CORRADE_TARGET_IOS) + set_target_properties(magnum-al-info PROPERTIES + MACOSX_BUNDLE ON + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/MacOSXBundleInfo.plist.in + XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "YES") + endif() + + # Magnum AL info target alias for superprojects + add_executable(Magnum::al-info ALIAS magnum-al-info) +endif() + if(BUILD_TESTS) add_subdirectory(Test) endif() - -# Magnum Audio target alias for superprojects -add_library(Magnum::Audio ALIAS MagnumAudio) diff --git a/src/Magnum/Audio/Context.cpp b/src/Magnum/Audio/Context.cpp index 70a331db2..a1aa20d2d 100644 --- a/src/Magnum/Audio/Context.cpp +++ b/src/Magnum/Audio/Context.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -44,6 +45,9 @@ const std::vector& Extension::extensions() { static const std::vector extensions{ _extension(AL,EXT,FLOAT32), _extension(AL,EXT,DOUBLE), + _extension(AL,EXT,ALAW), + _extension(AL,EXT,MULAW), + _extension(AL,EXT,MCFORMATS), _extension(ALC,EXT,ENUMERATION), _extension(ALC,SOFTX,HRTF), _extension(ALC,SOFT,HRTF) @@ -55,6 +59,7 @@ const std::vector& Extension::extensions() { Debug& operator<<(Debug& debug, const Context::HrtfStatus value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Context::HrtfStatus::value: return debug << "Audio::Context::HrtfStatus::" #value; _c(Disabled) _c(Enabled) @@ -63,13 +68,23 @@ Debug& operator<<(Debug& debug, const Context::HrtfStatus value) { _c(Detected) _c(UnsupportedFormat) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Audio::Context::HrtfStatus::(invalid)"; + return debug << "Audio::Context::HrtfStatus(" << Debug::nospace << reinterpret_cast(ALenum(value)) << Debug::nospace << ")"; } Context* Context::_current = nullptr; +std::vector Context::deviceSpecifierStrings() { + std::vector list; + const char* const devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER); + for(const char* device = devices; *device; device += std::strlen(device) + 1) + list.push_back(device); + + return list; +} + bool Context::hasCurrent() { return _current; } Context& Context::current() { @@ -82,11 +97,10 @@ Context::Context(): Context{Configuration{}} {} Context::Context(const Configuration& config) { CORRADE_ASSERT(!_current, "Audio::Context: context already created", ); - /* Open default device */ - const ALCchar* const defaultDevice = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER); - _device = alcOpenDevice(defaultDevice); - if(!_device) { - Error() << "Audio::Context: cannot open sound device" << defaultDevice; + /* Open the device */ + const ALCchar* const deviceSpecifier = config.deviceSpecifier().empty() ? alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER) : config.deviceSpecifier().data(); + if(!(_device = alcOpenDevice(deviceSpecifier))) { + Error() << "Audio::Context: cannot open sound device" << deviceSpecifier; std::exit(1); } @@ -184,4 +198,17 @@ bool Context::tryCreateContext(const Configuration& config) { return !!_context; } +Context::Configuration::Configuration() = default; +Context::Configuration::~Configuration() = default; + +Context::Configuration& Context::Configuration::setDeviceSpecifier(const std::string& specifier) { + _deviceSpecifier = specifier; + return *this; +} + +Context::Configuration& Context::Configuration::setDeviceSpecifier(std::string&& specifier) { + _deviceSpecifier = std::move(specifier); + return *this; +} + }} diff --git a/src/Magnum/Audio/Context.h b/src/Magnum/Audio/Context.h index 29156c348..dc68741ed 100644 --- a/src/Magnum/Audio/Context.h +++ b/src/Magnum/Audio/Context.h @@ -83,7 +83,6 @@ class MAGNUM_AUDIO_EXPORT Extension { */ class MAGNUM_AUDIO_EXPORT Context { public: - /** * @brief HRTF status * @@ -127,6 +126,14 @@ class MAGNUM_AUDIO_EXPORT Context { UnsupportedFormat = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT }; + /** + * @brief All device specifier strings + * + * @see @ref deviceSpecifierString(), @ref Configuration::setDeviceSpecifier() + * @fn_al{GetString} with @def_alc{DEVICE_SPECIFIER} + */ + static std::vector deviceSpecifierStrings(); + /** * @brief Whether there is any current context * @@ -202,17 +209,27 @@ class MAGNUM_AUDIO_EXPORT Context { return alcGetString(_device, ALC_HRTF_SPECIFIER_SOFT); } + /** + * @brief Device specifier string + * + * @see @ref deviceSpecifierStrings(), @ref vendorString(), @ref rendererString(), + * @fn_al{GetString} with @def_alc{DEVICE_SPECIFIER} + */ + std::string deviceSpecifierString() const { return alcGetString(_device, ALC_DEVICE_SPECIFIER); } + /** * @brief Vendor string * - * @see @ref rendererString(), @fn_al{GetString} with @def_al{VENDOR} + * @see @ref deviceSpecifierString(), @ref rendererString(), + * @fn_al{GetString} with @def_al{VENDOR} */ std::string vendorString() const { return alGetString(AL_VENDOR); } /** * @brief Renderer string * - * @see @ref vendorString(), @fn_al{GetString} with @def_al{RENDERER} + * @see @ref deviceSpecifierString(), @ref vendorString(), + * @fn_al{GetString} with @def_al{RENDERER} */ std::string rendererString() const { return alGetString(AL_RENDERER); } @@ -314,13 +331,22 @@ class MAGNUM_AUDIO_EXPORT Context::Configuration { Disabled = 2 /**< Disabled */ }; - /** @brief Constructor */ - explicit Configuration(): - _frequency(-1), - _monoSources(-1), - _stereoSources(-1), - _refreshRate(-1) - {} + explicit Configuration(); + ~Configuration(); + + /** @brief Device specifier */ + const std::string& deviceSpecifier() const { return _deviceSpecifier; } + + /** + * @brief Set device specifier + * @return Reference to self (for method chaining) + * + * If set to empty string (the default), default device specifier is + * used. + * @see @ref Context::deviceSpecifierStrings() + */ + Configuration& setDeviceSpecifier(const std::string& specifier); + Configuration& setDeviceSpecifier(std::string&& specifier); /**< @overload */ /** @brief Sampling rate in Hz */ Int frequency() const { return _frequency; } @@ -397,13 +423,15 @@ class MAGNUM_AUDIO_EXPORT Context::Configuration { } private: - Int _frequency; - Hrtf _hrtf; + std::string _deviceSpecifier; + + Int _frequency{-1}; + Hrtf _hrtf{}; - Int _monoSources; - Int _stereoSources; + Int _monoSources{-1}; + Int _stereoSources{-1}; - Int _refreshRate; + Int _refreshRate{-1}; }; diff --git a/src/Magnum/Audio/Extensions.h b/src/Magnum/Audio/Extensions.h index 478903e56..b9993d6d0 100644 --- a/src/Magnum/Audio/Extensions.h +++ b/src/Magnum/Audio/Extensions.h @@ -79,6 +79,9 @@ namespace AL { namespace EXT { _extension(AL,EXT,FLOAT32) // #??? _extension(AL,EXT,DOUBLE) // #??? + _extension(AL,EXT,ALAW) // #??? + _extension(AL,EXT,MULAW) // #??? + _extension(AL,EXT,MCFORMATS) // #??? } } namespace ALC { namespace EXT { diff --git a/src/Magnum/Audio/MacOSXBundleInfo.plist.in b/src/Magnum/Audio/MacOSXBundleInfo.plist.in new file mode 100644 index 000000000..ee4083277 --- /dev/null +++ b/src/Magnum/Audio/MacOSXBundleInfo.plist.in @@ -0,0 +1,18 @@ + + + + + CFBundleDevelopmentRegion + en-US + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIdentifier + cz.mosra.magnum.magnum-al-info + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + magnum-al-info + CFBundlePackageType + APPL + + diff --git a/src/Magnum/Audio/Renderer.cpp b/src/Magnum/Audio/Renderer.cpp index db5fcee9b..69e7be426 100644 --- a/src/Magnum/Audio/Renderer.cpp +++ b/src/Magnum/Audio/Renderer.cpp @@ -31,6 +31,7 @@ namespace Magnum { namespace Audio { Debug& operator<<(Debug& debug, const Renderer::Error value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Renderer::Error::value: return debug << "Audio::Renderer::Error::" #value; _c(NoError) _c(InvalidName) @@ -39,13 +40,15 @@ Debug& operator<<(Debug& debug, const Renderer::Error value) { _c(InvalidOperation) _c(OutOfMemory) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Audio::Renderer::Error::(invalid)"; + return debug << "Audio::Renderer::Error(" << Debug::nospace << reinterpret_cast(ALenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const Renderer::DistanceModel value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Renderer::DistanceModel::value: return debug << "Audio::Renderer::DistanceModel::" #value; _c(None) _c(Inverse) @@ -55,9 +58,10 @@ Debug& operator<<(Debug& debug, const Renderer::DistanceModel value) { _c(Exponent) _c(ExponentClamped) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Audio::Renderer::DistanceModel::(invalid)"; + return debug << "Audio::Renderer::DistanceModel(" << Debug::nospace << reinterpret_cast(ALenum(value)) << Debug::nospace << ")"; } }} diff --git a/src/Magnum/Audio/Source.cpp b/src/Magnum/Audio/Source.cpp index 7e47c1f5e..7c3554b15 100644 --- a/src/Magnum/Audio/Source.cpp +++ b/src/Magnum/Audio/Source.cpp @@ -98,15 +98,17 @@ void Source::rewind(const std::vector>& sources) Debug& operator<<(Debug& debug, const Source::State value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Source::State::value: return debug << "Audio::Source::State::" #value; _c(Initial) _c(Playing) _c(Paused) _c(Stopped) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Audio::Source::State::(invalid)"; + return debug << "Audio::Source::State(" << Debug::nospace << reinterpret_cast(ALint(value)) << Debug::nospace << ")"; } }} diff --git a/src/Magnum/Trade/Test/AbstractMaterialDataTest.cpp b/src/Magnum/Audio/Test/BufferALTest.cpp similarity index 68% rename from src/Magnum/Trade/Test/AbstractMaterialDataTest.cpp rename to src/Magnum/Audio/Test/BufferALTest.cpp index 7d4054031..298ae9c18 100644 --- a/src/Magnum/Trade/Test/AbstractMaterialDataTest.cpp +++ b/src/Magnum/Audio/Test/BufferALTest.cpp @@ -23,31 +23,30 @@ DEALINGS IN THE SOFTWARE. */ -#include #include -#include "Magnum/Trade/AbstractMaterialData.h" +#include "Magnum/Audio/Buffer.h" +#include "Magnum/Audio/Context.h" -namespace Magnum { namespace Trade { namespace Test { +namespace Magnum { namespace Audio { namespace Test { -class AbstractMaterialDataTest: public TestSuite::Tester { - public: - explicit AbstractMaterialDataTest(); +struct BufferALTest: TestSuite::Tester { + explicit BufferALTest(); - void debug(); + void construct(); + + Context _context; }; -AbstractMaterialDataTest::AbstractMaterialDataTest() { - addTests({&AbstractMaterialDataTest::debug}); +BufferALTest::BufferALTest() { + addTests({&BufferALTest::construct}); } -void AbstractMaterialDataTest::debug() { - std::ostringstream out; - - Debug(&out) << MaterialType::Phong; - CORRADE_COMPARE(out.str(), "Trade::MaterialType::Phong\n"); +void BufferALTest::construct() { + Buffer buf; + CORRADE_VERIFY(buf.id() != 0); } }}} -CORRADE_TEST_MAIN(Magnum::Trade::Test::AbstractMaterialDataTest) +CORRADE_TEST_MAIN(Magnum::Audio::Test::BufferALTest) diff --git a/src/Magnum/Audio/Test/BufferTest.cpp b/src/Magnum/Audio/Test/BufferTest.cpp index c98c6e746..76bb55625 100644 --- a/src/Magnum/Audio/Test/BufferTest.cpp +++ b/src/Magnum/Audio/Test/BufferTest.cpp @@ -42,8 +42,8 @@ BufferTest::BufferTest() { void BufferTest::debugFormat() { std::ostringstream out; - Debug(&out) << Buffer::Format::Stereo16; - CORRADE_COMPARE(out.str(), "Audio::Buffer::Format::Stereo16\n"); + Debug(&out) << Buffer::Format::Stereo16 << Buffer::Format(0xdead); + CORRADE_COMPARE(out.str(), "Audio::Buffer::Format::Stereo16 Audio::Buffer::Format(0xdead)\n"); } }}} diff --git a/src/Magnum/Audio/Test/CMakeLists.txt b/src/Magnum/Audio/Test/CMakeLists.txt index 939cecd9c..83a33b70f 100644 --- a/src/Magnum/Audio/Test/CMakeLists.txt +++ b/src/Magnum/Audio/Test/CMakeLists.txt @@ -24,6 +24,12 @@ # DEALINGS IN THE SOFTWARE. # +if(CORRADE_TARGET_EMSCRIPTEN) + set(AUDIO_TEST_DIR "") +else() + set(AUDIO_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure.h) @@ -34,7 +40,18 @@ corrade_add_test(AudioContextTest ContextTest.cpp LIBRARIES MagnumAudio) corrade_add_test(AudioRendererTest RendererTest.cpp LIBRARIES MagnumAudio) corrade_add_test(AudioSourceTest SourceTest.cpp LIBRARIES MagnumAudio) -if(WITH_SCENEGRAPH) - corrade_add_test(AudioListenerTest ListenerTest.cpp LIBRARIES MagnumSceneGraph MagnumAudio) - corrade_add_test(AudioPlayableTest PlayableTest.cpp LIBRARIES MagnumSceneGraph MagnumAudio) +if(BUILD_AL_TESTS) + corrade_add_test(AudioBufferALTest BufferALTest.cpp LIBRARIES MagnumAudio) + corrade_add_test(AudioContextALTest ContextALTest.cpp LIBRARIES MagnumAudio) + corrade_add_test(AudioRendererALTest RendererALTest.cpp LIBRARIES MagnumAudio) + corrade_add_test(AudioSourceALTest SourceALTest.cpp LIBRARIES MagnumAudio) + + if(WITH_SCENEGRAPH) + corrade_add_test(AudioListenerALTest ListenerALTest.cpp LIBRARIES MagnumSceneGraph MagnumAudio) + corrade_add_test(AudioPlayableALTest PlayableALTest.cpp LIBRARIES MagnumSceneGraph MagnumAudio) + endif() +endif() + +if(CORRADE_TARGET_EMSCRIPTEN) + emscripten_embed_file(AudioAbstractImporterTest file.bin "/file.bin") endif() diff --git a/src/Magnum/Audio/Test/ContextALTest.cpp b/src/Magnum/Audio/Test/ContextALTest.cpp new file mode 100644 index 000000000..cdb7d0879 --- /dev/null +++ b/src/Magnum/Audio/Test/ContextALTest.cpp @@ -0,0 +1,60 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2015 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Audio/Extensions.h" +#include "Magnum/Audio/Context.h" + +namespace Magnum { namespace Audio { namespace Test { + +struct ContextALTest: TestSuite::Tester { + explicit ContextALTest(); + + void extensionsString(); + void isExtensionEnabled(); + + Context _context; +}; + +ContextALTest::ContextALTest() { + addTests({&ContextALTest::extensionsString, + &ContextALTest::isExtensionEnabled}); +} + +void ContextALTest::extensionsString() { + std::vector extensions = _context.extensionStrings(); + + CORRADE_VERIFY(!extensions.empty()); +} + +void ContextALTest::isExtensionEnabled() { + CORRADE_VERIFY(Context::current().isExtensionSupported()); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Audio::Test::ContextALTest) diff --git a/src/Magnum/Audio/Test/ContextTest.cpp b/src/Magnum/Audio/Test/ContextTest.cpp index bb15c2856..5a0b1dbf5 100644 --- a/src/Magnum/Audio/Test/ContextTest.cpp +++ b/src/Magnum/Audio/Test/ContextTest.cpp @@ -27,7 +27,6 @@ #include #include -#include "Magnum/Audio/Extensions.h" #include "Magnum/Audio/Context.h" namespace Magnum { namespace Audio { namespace Test { @@ -35,34 +34,17 @@ namespace Magnum { namespace Audio { namespace Test { struct ContextTest: TestSuite::Tester { explicit ContextTest(); - void extensionsString(); - void isExtensionEnabled(); - void hrtfStatus(); - void hrtfs(); - - Context _context; + void debugHrtfStatus(); }; ContextTest::ContextTest() { - addTests({&ContextTest::extensionsString, - &ContextTest::isExtensionEnabled, - &ContextTest::hrtfStatus}); -} - -void ContextTest::extensionsString() { - std::vector extensions = _context.extensionStrings(); - - CORRADE_VERIFY(extensions.size() > 0); -} - -void ContextTest::isExtensionEnabled() { - CORRADE_VERIFY(Context::current().isExtensionSupported()); + addTests({&ContextTest::debugHrtfStatus}); } -void ContextTest::hrtfStatus() { +void ContextTest::debugHrtfStatus() { std::ostringstream out; - Debug(&out) << Context::HrtfStatus::Denied; - CORRADE_COMPARE(out.str(), "Audio::Context::HrtfStatus::Denied\n"); + Debug(&out) << Context::HrtfStatus::Denied << Context::HrtfStatus(0xdead); + CORRADE_COMPARE(out.str(), "Audio::Context::HrtfStatus::Denied Audio::Context::HrtfStatus(0xdead)\n"); } }}} diff --git a/src/Magnum/Audio/Test/ListenerTest.cpp b/src/Magnum/Audio/Test/ListenerALTest.cpp similarity index 81% rename from src/Magnum/Audio/Test/ListenerTest.cpp rename to src/Magnum/Audio/Test/ListenerALTest.cpp index 2e22aa32c..dea7ce4b2 100644 --- a/src/Magnum/Audio/Test/ListenerTest.cpp +++ b/src/Magnum/Audio/Test/ListenerALTest.cpp @@ -26,15 +26,14 @@ #include -#include -#include -#include -#include - #include "Magnum/Audio/Playable.h" #include "Magnum/Audio/Context.h" #include "Magnum/Audio/Listener.h" #include "Magnum/Audio/PlayableGroup.h" +#include "Magnum/SceneGraph/Scene.h" +#include "Magnum/SceneGraph/Object.h" +#include "Magnum/SceneGraph/MatrixTransformation2D.h" +#include "Magnum/SceneGraph/MatrixTransformation3D.h" namespace Magnum { namespace Audio { namespace Test { @@ -44,23 +43,23 @@ typedef SceneGraph::Object Object2D; typedef SceneGraph::Scene Scene3D; typedef SceneGraph::Object Object3D; -struct ListenerTest: TestSuite::Tester { - explicit ListenerTest(); +struct ListenerALTest: TestSuite::Tester { + explicit ListenerALTest(); - void testFeature2D(); - void testFeature3D(); - void testUpdateGroups(); + void feature2D(); + void feature3D(); + void updateGroups(); Context _context; }; -ListenerTest::ListenerTest(): _context() { - addTests({&ListenerTest::testFeature2D, - &ListenerTest::testFeature3D, - &ListenerTest::testUpdateGroups}); +ListenerALTest::ListenerALTest() { + addTests({&ListenerALTest::feature2D, + &ListenerALTest::feature3D, + &ListenerALTest::updateGroups}); } -void ListenerTest::testFeature2D() { +void ListenerALTest::feature2D() { Scene2D scene; Object2D object{&scene}; Listener2D listener{object}; @@ -72,7 +71,7 @@ void ListenerTest::testFeature2D() { CORRADE_COMPARE(Renderer::listenerPosition(), offset); } -void ListenerTest::testFeature3D() { +void ListenerALTest::feature3D() { Scene3D scene; Object3D object{&scene}; Listener3D listener{object}; @@ -84,7 +83,7 @@ void ListenerTest::testFeature3D() { CORRADE_COMPARE(Renderer::listenerPosition(), offset); } -void ListenerTest::testUpdateGroups() { +void ListenerALTest::updateGroups() { Scene3D scene; Object3D sourceObject{&scene}; Object3D object{&scene}; @@ -108,4 +107,4 @@ void ListenerTest::testUpdateGroups() { }}} -CORRADE_TEST_MAIN(Magnum::Audio::Test::ListenerTest) +CORRADE_TEST_MAIN(Magnum::Audio::Test::ListenerALTest) diff --git a/src/Magnum/Audio/Test/PlayableTest.cpp b/src/Magnum/Audio/Test/PlayableALTest.cpp similarity index 84% rename from src/Magnum/Audio/Test/PlayableTest.cpp rename to src/Magnum/Audio/Test/PlayableALTest.cpp index 3a185d18a..567b342cc 100644 --- a/src/Magnum/Audio/Test/PlayableTest.cpp +++ b/src/Magnum/Audio/Test/PlayableALTest.cpp @@ -26,33 +26,32 @@ #include -#include -#include -#include - #include "Magnum/Audio/Context.h" #include "Magnum/Audio/Playable.h" +#include "Magnum/SceneGraph/Scene.h" +#include "Magnum/SceneGraph/Object.h" +#include "Magnum/SceneGraph/MatrixTransformation3D.h" namespace Magnum { namespace Audio { namespace Test { typedef SceneGraph::Scene Scene3D; typedef SceneGraph::Object Object3D; -struct PlayableTest: TestSuite::Tester { - explicit PlayableTest(); +struct PlayableALTest: TestSuite::Tester { + explicit PlayableALTest(); - void testFeature(); - void testGroup(); + void feature(); + void group(); Context _context; }; -PlayableTest::PlayableTest() { - addTests({&PlayableTest::testFeature, - &PlayableTest::testGroup}); +PlayableALTest::PlayableALTest() { + addTests({&PlayableALTest::feature, + &PlayableALTest::group}); } -void PlayableTest::testFeature() { +void PlayableALTest::feature() { Scene3D scene; Object3D object{&scene}; Source source; @@ -65,7 +64,7 @@ void PlayableTest::testFeature() { CORRADE_COMPARE(playable.source().position(), offset); } -void PlayableTest::testGroup() { +void PlayableALTest::group() { Scene3D scene; Object3D object{&scene}; Source source; @@ -94,4 +93,4 @@ void PlayableTest::testGroup() { }}} -CORRADE_TEST_MAIN(Magnum::Audio::Test::PlayableTest) +CORRADE_TEST_MAIN(Magnum::Audio::Test::PlayableALTest) diff --git a/src/Magnum/Audio/Test/RendererALTest.cpp b/src/Magnum/Audio/Test/RendererALTest.cpp new file mode 100644 index 000000000..04671df93 --- /dev/null +++ b/src/Magnum/Audio/Test/RendererALTest.cpp @@ -0,0 +1,110 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Audio/Context.h" +#include "Magnum/Audio/Renderer.h" + +namespace Magnum { namespace Audio { namespace Test { + +struct RendererALTest: TestSuite::Tester { + explicit RendererALTest(); + + void listenerOrientation(); + void listenerPosition(); + void listenerVelocity(); + void listenerGain(); + void speedOfSound(); + void dopplerFactor(); + void distanceModel(); + + Context _context; +}; + +RendererALTest::RendererALTest() { + addTests({&RendererALTest::listenerOrientation, + &RendererALTest::listenerPosition, + &RendererALTest::listenerVelocity, + &RendererALTest::listenerGain, + &RendererALTest::speedOfSound, + &RendererALTest::dopplerFactor, + &RendererALTest::distanceModel}); +} + +void RendererALTest::listenerOrientation() { + constexpr Vector3 up{1.0f, 2.0f, 3.0f}, fwd{3.0f, 2.0f, 1.0f}; + Renderer::setListenerOrientation(fwd, up); + std::array orientation = Renderer::listenerOrientation(); + + CORRADE_COMPARE(orientation[0], fwd); + CORRADE_COMPARE(orientation[1], up); +} + +void RendererALTest::listenerPosition() { + constexpr Vector3 pos{1.0f, 3.0f, 2.0f}; + Renderer::setListenerPosition(pos); + + CORRADE_COMPARE(Renderer::listenerPosition(), pos); +} + +void RendererALTest::listenerVelocity() { + constexpr Vector3 vel{1.0f, 3.0f, 2.0f}; + Renderer::setListenerVelocity(vel); + + CORRADE_COMPARE(Renderer::listenerVelocity(), vel); +} + +void RendererALTest::listenerGain() { + constexpr Float gain = 0.512f; + Renderer::setListenerGain(gain); + + CORRADE_COMPARE(Renderer::listenerGain(), gain); +} + +void RendererALTest::speedOfSound() { + constexpr Float speed = 1.25f; + Renderer::setSpeedOfSound(speed); + + CORRADE_COMPARE(Renderer::speedOfSound(), speed); +} + +void RendererALTest::dopplerFactor() { + constexpr Float factor = 0.3335f; + Renderer::setDopplerFactor(factor); + + CORRADE_COMPARE(Renderer::dopplerFactor(), factor); +} + +void RendererALTest::distanceModel() { + constexpr Renderer::DistanceModel model = Renderer::DistanceModel::InverseClamped; + Renderer::setDistanceModel(model); + + CORRADE_COMPARE(Renderer::distanceModel(), model); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Audio::Test::RendererALTest) diff --git a/src/Magnum/Audio/Test/RendererTest.cpp b/src/Magnum/Audio/Test/RendererTest.cpp index 634865b82..ea6b7ef32 100644 --- a/src/Magnum/Audio/Test/RendererTest.cpp +++ b/src/Magnum/Audio/Test/RendererTest.cpp @@ -27,7 +27,6 @@ #include #include "Magnum/Magnum.h" -#include "Magnum/Audio/Context.h" #include "Magnum/Audio/Renderer.h" namespace Magnum { namespace Audio { namespace Test { @@ -37,90 +36,23 @@ struct RendererTest: TestSuite::Tester { void debugError(); void debugDistanceModel(); - void listenerOrientation(); - void listenerPosition(); - void listenerVelocity(); - void listenerGain(); - void speedOfSound(); - void dopplerFactor(); - void distanceModel(); - - Context _context; }; RendererTest::RendererTest() { addTests({&RendererTest::debugError, - &RendererTest::debugDistanceModel, - &RendererTest::listenerOrientation, - &RendererTest::listenerPosition, - &RendererTest::listenerVelocity, - &RendererTest::listenerGain, - &RendererTest::speedOfSound, - &RendererTest::dopplerFactor, - &RendererTest::distanceModel}); + &RendererTest::debugDistanceModel}); } void RendererTest::debugError() { std::ostringstream out; - Debug(&out) << Renderer::Error::InvalidOperation; - CORRADE_COMPARE(out.str(), "Audio::Renderer::Error::InvalidOperation\n"); + Debug(&out) << Renderer::Error::InvalidOperation << Renderer::Error(0xdead); + CORRADE_COMPARE(out.str(), "Audio::Renderer::Error::InvalidOperation Audio::Renderer::Error(0xdead)\n"); } void RendererTest::debugDistanceModel() { std::ostringstream out; - Debug(&out) << Renderer::DistanceModel::Inverse; - CORRADE_COMPARE(out.str(), "Audio::Renderer::DistanceModel::Inverse\n"); -} - -void RendererTest::listenerOrientation() { - constexpr Vector3 up{1.0f, 2.0f, 3.0f}, fwd{3.0f, 2.0f, 1.0f}; - Renderer::setListenerOrientation(fwd, up); - std::array orientation = Renderer::listenerOrientation(); - - CORRADE_COMPARE(orientation[0], fwd); - CORRADE_COMPARE(orientation[1], up); -} - -void RendererTest::listenerPosition() { - constexpr Vector3 pos{1.0f, 3.0f, 2.0f}; - Renderer::setListenerPosition(pos); - - CORRADE_COMPARE(Renderer::listenerPosition(), pos); -} - -void RendererTest::listenerVelocity() { - constexpr Vector3 vel{1.0f, 3.0f, 2.0f}; - Renderer::setListenerVelocity(vel); - - CORRADE_COMPARE(Renderer::listenerVelocity(), vel); -} - -void RendererTest::listenerGain() { - constexpr Float gain = 0.512f; - Renderer::setListenerGain(gain); - - CORRADE_COMPARE(Renderer::listenerGain(), gain); -} - -void RendererTest::speedOfSound() { - constexpr Float speed = 1.25f; - Renderer::setSpeedOfSound(speed); - - CORRADE_COMPARE(Renderer::speedOfSound(), speed); -} - -void RendererTest::dopplerFactor() { - constexpr Float factor = 0.3335f; - Renderer::setDopplerFactor(factor); - - CORRADE_COMPARE(Renderer::dopplerFactor(), factor); -} - -void RendererTest::distanceModel() { - constexpr Renderer::DistanceModel model = Renderer::DistanceModel::InverseClamped; - Renderer::setDistanceModel(model); - - CORRADE_COMPARE(Renderer::distanceModel(), model); + Debug(&out) << Renderer::DistanceModel::Inverse << Renderer::DistanceModel(0xdead); + CORRADE_COMPARE(out.str(), "Audio::Renderer::DistanceModel::Inverse Audio::Renderer::DistanceModel(0xdead)\n"); } }}} diff --git a/src/Magnum/Audio/Test/SourceALTest.cpp b/src/Magnum/Audio/Test/SourceALTest.cpp new file mode 100644 index 000000000..7dfa190c8 --- /dev/null +++ b/src/Magnum/Audio/Test/SourceALTest.cpp @@ -0,0 +1,173 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Audio/Context.h" +#include "Magnum/Audio/Source.h" + +namespace Magnum { namespace Audio { namespace Test { + +struct SourceALTest: TestSuite::Tester { + explicit SourceALTest(); + + void construct(); + + void position(); + void direction(); + void velocity(); + void gain(); + void looping(); + void relative(); + void maxDistance(); + void maxGain(); + void minGain(); + void coneAnglesAndGain(); + void rolloffFactor(); + + Context _context; +}; + +SourceALTest::SourceALTest() { + addTests({&SourceALTest::construct, + + &SourceALTest::position, + &SourceALTest::direction, + &SourceALTest::velocity, + &SourceALTest::gain, + &SourceALTest::looping, + &SourceALTest::relative, + &SourceALTest::maxDistance, + &SourceALTest::maxGain, + &SourceALTest::minGain, + &SourceALTest::coneAnglesAndGain, + &SourceALTest::rolloffFactor}); +} + +void SourceALTest::construct() { + Source source; + CORRADE_VERIFY(source.id() != 0); +} + +void SourceALTest::position() { + Source source; + constexpr Vector3 pos{3.0f, 5.0f, 6.0f}; + source.setPosition(pos); + + CORRADE_COMPARE(source.position(), pos); +} + +void SourceALTest::direction() { + Source source; + constexpr Vector3 dir{3.0f, 1.0f, 2.0f}; + source.setDirection(dir); + + CORRADE_COMPARE(source.direction(), dir); +} + +void SourceALTest::velocity() { + Source source; + constexpr Vector3 vel{-3.0f, 5.0f, -6.0f}; + source.setVelocity(vel); + + CORRADE_COMPARE(source.velocity(), vel); +} + +void SourceALTest::gain() { + Source source; + constexpr Float gain = 0.1234f; + source.setGain(gain); + + CORRADE_COMPARE(source.gain(), gain); +} + +void SourceALTest::looping() { + Source source; + source.setLooping(true); + CORRADE_VERIFY(source.isLooping()); + source.setLooping(false); + CORRADE_VERIFY(!source.isLooping()); +} + +void SourceALTest::relative() { + Source source; + source.setRelative(true); + CORRADE_VERIFY(source.isRelative()); + source.setRelative(false); + CORRADE_VERIFY(!source.isRelative()); +} + +void SourceALTest::maxDistance() { + Source source; + constexpr Float dist = 0.222f; + source.setMaxDistance(dist); + + CORRADE_COMPARE(source.maxDistance(), dist); +} + +void SourceALTest::maxGain() { + Source source; + constexpr Float gain = 0.3131f; + source.setMaxGain(gain); + + CORRADE_COMPARE(source.maxGain(), gain); +} + +void SourceALTest::minGain() { + Source source; + constexpr Float gain = 0.4144f; + source.setMinGain(gain); + + CORRADE_COMPARE(source.minGain(), gain); +} + +void SourceALTest::coneAnglesAndGain() { + using namespace Math::Literals; + + Source source; + constexpr auto outerAngle = 12.0_degf; + constexpr auto innerAngle = 21.0_degf; + constexpr Float outerGain = 0.05f; + + source.setInnerConeAngle(innerAngle); + source.setOuterConeAngle(outerAngle); + source.setOuterConeGain(outerGain); + + CORRADE_COMPARE(source.outerConeAngle(), outerAngle); + CORRADE_COMPARE(source.innerConeAngle(), innerAngle); + CORRADE_COMPARE(source.outerConeGain(), outerGain); +} + +void SourceALTest::rolloffFactor() { + Source source; + constexpr Float fact = 42.0f; + source.setRolloffFactor(fact); + + CORRADE_COMPARE(source.rolloffFactor(), fact); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Audio::Test::SourceALTest) diff --git a/src/Magnum/Audio/Test/SourceTest.cpp b/src/Magnum/Audio/Test/SourceTest.cpp index 563d66c52..521a04a3a 100644 --- a/src/Magnum/Audio/Test/SourceTest.cpp +++ b/src/Magnum/Audio/Test/SourceTest.cpp @@ -26,7 +26,6 @@ #include #include -#include "Magnum/Audio/Context.h" #include "Magnum/Audio/Source.h" namespace Magnum { namespace Audio { namespace Test { @@ -35,140 +34,18 @@ struct SourceTest: TestSuite::Tester { explicit SourceTest(); void debugState(); - void position(); - void direction(); - void velocity(); - void gain(); - void looping(); - void relative(); - void maxDistance(); - void maxGain(); - void minGain(); - void coneAnglesAndGain(); - void rolloffFactor(); - - Context _context; }; SourceTest::SourceTest() { - addTests({&SourceTest::debugState, - &SourceTest::position, - &SourceTest::direction, - &SourceTest::velocity, - &SourceTest::gain, - &SourceTest::looping, - &SourceTest::relative, - &SourceTest::maxDistance, - &SourceTest::maxGain, - &SourceTest::minGain, - &SourceTest::coneAnglesAndGain, - &SourceTest::rolloffFactor}); + addTests({&SourceTest::debugState}); } void SourceTest::debugState() { std::ostringstream out; - Debug(&out) << Source::State::Playing; - CORRADE_COMPARE(out.str(), "Audio::Source::State::Playing\n"); -} - -void SourceTest::position() { - Source source; - constexpr Vector3 pos{3.0f, 5.0f, 6.0f}; - source.setPosition(pos); - - CORRADE_COMPARE(source.position(), pos); -} - -void SourceTest::direction() { - Source source; - constexpr Vector3 dir{3.0f, 1.0f, 2.0f}; - source.setDirection(dir); - - CORRADE_COMPARE(source.direction(), dir); -} - -void SourceTest::velocity() { - Source source; - constexpr Vector3 vel{-3.0f, 5.0f, -6.0f}; - source.setVelocity(vel); - - CORRADE_COMPARE(source.velocity(), vel); + Debug(&out) << Source::State::Playing << Source::State(0xdead); + CORRADE_COMPARE(out.str(), "Audio::Source::State::Playing Audio::Source::State(0xdead)\n"); } -void SourceTest::gain() { - Source source; - constexpr Float gain = 0.1234f; - source.setGain(gain); - - CORRADE_COMPARE(source.gain(), gain); -} - -void SourceTest::looping() { - Source source; - source.setLooping(true); - CORRADE_VERIFY(source.isLooping()); - source.setLooping(false); - CORRADE_VERIFY(!source.isLooping()); -} - -void SourceTest::relative() { - Source source; - source.setRelative(true); - CORRADE_VERIFY(source.isRelative()); - source.setRelative(false); - CORRADE_VERIFY(!source.isRelative()); -} - -void SourceTest::maxDistance() { - Source source; - constexpr Float dist = 0.222f; - source.setMaxDistance(dist); - - CORRADE_COMPARE(source.maxDistance(), dist); -} - -void SourceTest::maxGain() { - Source source; - constexpr Float gain = 0.3131f; - source.setMaxGain(gain); - - CORRADE_COMPARE(source.maxGain(), gain); -} - -void SourceTest::minGain() { - Source source; - constexpr Float gain = 0.4144f; - source.setMinGain(gain); - - CORRADE_COMPARE(source.minGain(), gain); -} - -void SourceTest::coneAnglesAndGain() { - using namespace Math::Literals; - - Source source; - constexpr auto outerAngle = 12.0_degf; - constexpr auto innerAngle = 21.0_degf; - constexpr Float outerGain = 0.05f; - - source.setInnerConeAngle(innerAngle); - source.setOuterConeAngle(outerAngle); - source.setOuterConeGain(outerGain); - - CORRADE_COMPARE(source.outerConeAngle(), outerAngle); - CORRADE_COMPARE(source.innerConeAngle(), innerAngle); - CORRADE_COMPARE(source.outerConeGain(), outerGain); -} - -void SourceTest::rolloffFactor() { - Source source; - constexpr Float fact = 42.0f; - source.setRolloffFactor(fact); - - CORRADE_COMPARE(source.rolloffFactor(), fact); -} - - }}} CORRADE_TEST_MAIN(Magnum::Audio::Test::SourceTest) diff --git a/src/Magnum/Audio/Test/configure.h.cmake b/src/Magnum/Audio/Test/configure.h.cmake index 8208c7ca8..d2025143e 100644 --- a/src/Magnum/Audio/Test/configure.h.cmake +++ b/src/Magnum/Audio/Test/configure.h.cmake @@ -23,4 +23,4 @@ DEALINGS IN THE SOFTWARE. */ -#define AUDIO_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" +#define AUDIO_TEST_DIR "${AUDIO_TEST_DIR}" diff --git a/src/Magnum/Audio/magnum-al-info.cpp b/src/Magnum/Audio/magnum-al-info.cpp new file mode 100644 index 000000000..2910fb77c --- /dev/null +++ b/src/Magnum/Audio/magnum-al-info.cpp @@ -0,0 +1,112 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Audio/Context.h" + +namespace Magnum { + +/** @page magnum-al-info Magnum OpenAL Info +@brief Displays information about Magnum OpenAL capabilities + +@section magnum-al-info-usage Usage + + magnum-al-info [-h|--help] [-s|--short] [--extension-strings] + +Arguments: +- `-h`,` --help` -- display this help message and exit +- `-s`, `--short` -- display just essential info and exit +- `--extension-strings` -- list all extension strings provided by the driver + (implies `--short`) + +@section magnum-al-info-example Example output + +``` + +---------------------------------------------------------+ + | Information about Magnum engine and OpenAL capabilities | + +---------------------------------------------------------+ + +Audio Renderer: OpenAL Soft by OpenAL Community +OpenAL version: 1.1 ALSOFT 1.17.2 +Available devices: + OpenAL Soft +Current device: OpenAL Soft +Vendor extension support: + AL_EXT_FLOAT32 SUPPORTED + AL_EXT_DOUBLE SUPPORTED + AL_EXT_ALAW SUPPORTED + AL_EXT_MULAW SUPPORTED + AL_EXT_MCFORMATS SUPPORTED + ALC_ENUMERATION_EXT SUPPORTED + ALC_SOFTX_HRTF - + ALC_SOFT_HRTF SUPPORTED + +``` + +*/ + +} + +using namespace Magnum; + +int main(const int argc, const char** const argv) { + Utility::Arguments args; + args.addBooleanOption('s', "short").setHelp("short", "display just essential info and exit") + .addBooleanOption("extension-strings").setHelp("extension-strings", "list all extension strings provided by the driver (implies --short)") + .parse(argc, argv); + + Debug() << ""; + Debug() << " +---------------------------------------------------------+"; + Debug() << " | Information about Magnum engine and OpenAL capabilities |"; + Debug() << " +---------------------------------------------------------+"; + Debug() << ""; + + Audio::Context c; + Debug() << "Available devices:"; + for(const auto& device: Audio::Context::deviceSpecifierStrings()) + Debug() << " " << device; + Debug() << "Current device:" << c.deviceSpecifierString(); + + if(args.isSet("extension-strings")) { + Debug() << "Extension strings:" << Debug::newline + << c.extensionStrings(); + return 0; + } + + if(args.isSet("short")) return 0; + + Debug() << "Vendor extension support:"; + for(const auto& extension: Audio::Extension::extensions()) { + std::string extensionName = extension.string(); + Debug d; + d << " " << extensionName << std::string(60-extensionName.size(), ' '); + if(c.isExtensionSupported(extension)) + d << "SUPPORTED"; + else + d << " -"; + } +} diff --git a/src/Magnum/Buffer.cpp b/src/Magnum/Buffer.cpp index 00a72cd83..edfb3b000 100644 --- a/src/Magnum/Buffer.cpp +++ b/src/Magnum/Buffer.cpp @@ -537,7 +537,7 @@ void* Buffer::mapImplementationDefault(MapAccess access) { return glMapBufferOES(GLenum(bindSomewhereInternal(_targetHint)), GLenum(access)); #else static_cast(access); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -561,7 +561,7 @@ void* Buffer::mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, static_cast(offset); static_cast(length); static_cast(access); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -584,7 +584,7 @@ void Buffer::flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr l #else static_cast(offset); static_cast(length); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -605,7 +605,7 @@ bool Buffer::unmapImplementationDefault() { #elif !defined(CORRADE_TARGET_NACL) return glUnmapBufferOES(GLenum(bindSomewhereInternal(_targetHint))); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -624,6 +624,7 @@ bool Buffer::unmapImplementationDSAEXT() { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, Buffer::TargetHint value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Buffer::TargetHint::value: return debug << "Buffer::TargetHint::" #value; _c(Array) #ifndef MAGNUM_TARGET_GLES2 @@ -653,9 +654,10 @@ Debug& operator<<(Debug& debug, Buffer::TargetHint value) { _c(Uniform) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Buffer::TargetHint::(invalid)"; + return debug << "Buffer::TargetHint(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif @@ -674,6 +676,10 @@ Debug& operator<<(Debug& debug, Buffer::Target value) { #endif #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif case Buffer::Target::Array: #ifndef MAGNUM_TARGET_GLES2 case Buffer::Target::CopyRead: @@ -693,12 +699,15 @@ Debug& operator<<(Debug& debug, Buffer::Target value) { #endif #ifndef MAGNUM_TARGET_GLES2 case Buffer::Target::TransformFeedback: + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif return debug << static_cast(value); #endif } - return debug << "Buffer::Target::(invalid)"; + return debug << "Buffer::Target(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif #endif diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index a288276f9..72bfd3715 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -370,7 +370,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::Array instead. */ - Array = GL_ARRAY_BUFFER, + Array CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::Array instead") = GL_ARRAY_BUFFER, #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -391,14 +391,14 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::CopyRead instead. */ - CopyRead = GL_COPY_READ_BUFFER, + CopyRead CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::CopyRead instead") = GL_COPY_READ_BUFFER, /** * @copydoc TargetHint::CopyWrite * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::CopyWrite instead. */ - CopyWrite = GL_COPY_WRITE_BUFFER, + CopyWrite CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::CopyWrite instead") = GL_COPY_WRITE_BUFFER, #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -407,14 +407,14 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::DispatchIndirect instead. */ - DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER, + DispatchIndirect CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::DispatchIndirect instead") = GL_DISPATCH_INDIRECT_BUFFER, /** * @copydoc TargetHint::DrawIndirect * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::DrawIndirect instead. */ - DrawIndirect = GL_DRAW_INDIRECT_BUFFER, + DrawIndirect CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::DrawIndirect instead") = GL_DRAW_INDIRECT_BUFFER, #endif /** @@ -422,7 +422,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::ElementArray instead. */ - ElementArray = GL_ELEMENT_ARRAY_BUFFER, + ElementArray CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::ElementArray instead") = GL_ELEMENT_ARRAY_BUFFER, #ifndef MAGNUM_TARGET_GLES2 /** @@ -430,14 +430,14 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::PixelPack instead. */ - PixelPack = GL_PIXEL_PACK_BUFFER, + PixelPack CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::PixelPack instead") = GL_PIXEL_PACK_BUFFER, /** * @copydoc TargetHint::PixelUnpack * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::PixelUnpack instead. */ - PixelUnpack = GL_PIXEL_UNPACK_BUFFER, + PixelUnpack CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::PixelUnpack instead") = GL_PIXEL_UNPACK_BUFFER, #endif #endif @@ -458,7 +458,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::Texture instead. */ - Texture = GL_TEXTURE_BUFFER, + Texture CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::Texture instead") = GL_TEXTURE_BUFFER, #endif #if defined(MAGNUM_BUILD_DEPRECATED) && !defined(MAGNUM_TARGET_GLES2) @@ -467,7 +467,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @deprecated For @ref setTargetHint() only, use * @ref TargetHint::TransformFeedback instead. */ - TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER, + TransformFeedback CORRADE_DEPRECATED_ENUM("use Buffer::TargetHint::TransformFeedback instead") = GL_TRANSFORM_FEEDBACK_BUFFER, #endif #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/BufferImage.h b/src/Magnum/BufferImage.h index 7e351e6eb..8d63773be 100644 --- a/src/Magnum/BufferImage.h +++ b/src/Magnum/BufferImage.h @@ -145,7 +145,7 @@ template class BufferImage { * * See @ref PixelStorage::dataProperties() for more information. */ - std::tuple, std::size_t> dataProperties() const { + std::tuple, VectorTypeFor, std::size_t> dataProperties() const { return Implementation::imageDataProperties(*this); } @@ -333,7 +333,7 @@ template class CompressedBufferImage { * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * WebGL. */ - std::tuple, std::size_t> dataProperties() const { + std::tuple, VectorTypeFor, std::size_t> dataProperties() const { return Implementation::compressedImageDataProperties(*this); } #endif diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 52257c48f..6fdc91788 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -67,6 +67,7 @@ set(Magnum_SRCS Trade/AbstractImporter.cpp Trade/AbstractMaterialData.cpp Trade/ImageData.cpp + Trade/LightData.cpp Trade/MeshData2D.cpp Trade/MeshData3D.cpp Trade/MeshObjectData2D.cpp @@ -150,6 +151,7 @@ endif() if(NOT TARGET_GLES2) list(APPEND Magnum_SRCS BufferImage.cpp + PrimitiveQuery.cpp TextureArray.cpp TransformFeedback.cpp @@ -323,7 +325,7 @@ if(BUILD_TESTS) # Library with graceful assert for testing add_library(MagnumMathTestLib ${SHARED_OR_STATIC} $ - dummy.cpp) # XCode workaround, see file comment for details + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details target_include_directories(MagnumMathTestLib PUBLIC $) target_compile_definitions(MagnumMathTestLib PRIVATE "CORRADE_GRACEFUL_ASSERT") set_target_properties(MagnumMathTestLib PROPERTIES DEBUG_POSTFIX "-d") diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index b8bf0590e..c1294da14 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -25,6 +25,7 @@ #include "Context.h" +#include /* for initialization log redirection */ #include #include #include @@ -64,6 +65,7 @@ const std::vector& Extension::extensions(Version version) { static const std::vector empty; #ifndef MAGNUM_TARGET_GLES static const std::vector extensions{ + _extension(GL,AMD,transform_feedback3_lines_triangles), _extension(GL,AMD,vertex_shader_layer), _extension(GL,AMD,shader_trinary_minmax), _extension(GL,ARB,robustness), @@ -241,6 +243,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,OES,element_index_uint), _extension(GL,OES,texture_float_linear), _extension(GL,OES,texture_half_float_linear), + _extension(GL,OES,fbo_render_mipmap), _extension(GL,WEBGL,compressed_texture_s3tc), _extension(GL,WEBGL,depth_texture), _extension(GL,WEBGL,draw_buffers)}; @@ -355,6 +358,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,NV,shadow_samplers_cube), _extension(GL,OES,depth24), _extension(GL,OES,element_index_uint), + _extension(GL,OES,fbo_render_mipmap), _extension(GL,OES,rgb8_rgba8), _extension(GL,OES,texture_3D), _extension(GL,OES,texture_half_float_linear), @@ -404,28 +408,42 @@ const std::vector& Extension::extensions(Version version) { #endif } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } -Context* Context::_current = nullptr; +namespace { + #ifdef MAGNUM_BUILD_MULTITHREADED + #if !defined(CORRADE_GCC47_COMPATIBILITY) && !defined(CORRADE_TARGET_APPLE) + thread_local + #else + __thread + #endif + #endif + Context* currentContext = nullptr; +} -bool Context::hasCurrent() { return _current; } +bool Context::hasCurrent() { return currentContext; } Context& Context::current() { - CORRADE_ASSERT(_current, "Context::current(): no current context", *_current); - return *_current; + CORRADE_ASSERT(currentContext, "Context::current(): no current context", *currentContext); + return *currentContext; } -Context::Context(NoCreateT, Int argc, char** argv, void functionLoader()): _functionLoader{functionLoader}, _version{Version::None} { +Context::Context(NoCreateT, Int argc, const char** argv, void functionLoader()): _functionLoader{functionLoader}, _version{Version::None} { /* Parse arguments */ Utility::Arguments args{"magnum"}; args.addOption("disable-workarounds") .setHelp("disable-workarounds", "driver workarounds to disable\n (see src/Magnum/Implementation/driverSpecific.cpp for detailed info)", "LIST") .addOption("disable-extensions").setHelp("disable-extensions", "OpenGL extensions to disable", "LIST") + .addOption("log", "default").setHelp("log", "Console logging", "default|quiet") .setFromEnvironment("disable-workarounds") .setFromEnvironment("disable-extensions") + .setFromEnvironment("log") .parse(argc, argv); + /* Decide whether to display initialization log */ + _displayInitializationLog = !(args.value("log") == "quiet" || args.value("log") == "QUIET"); + /* Disable driver workarounds */ for(auto&& workaround: Utility::String::splitWithoutEmptyParts(args.value("disable-workarounds"))) disableDriverWorkaround(workaround); @@ -446,13 +464,13 @@ Context::Context(Context&& other): _version{std::move(other._version)}, _detectedDrivers{std::move(other._detectedDrivers)} { other._state = nullptr; - if(_current == &other) _current = this; + if(currentContext == &other) currentContext = this; } Context::~Context() { delete _state; - if(_current == this) _current = nullptr; + if(currentContext == this) currentContext = nullptr; } void Context::create() { @@ -638,17 +656,20 @@ bool Context::tryCreate() { setupDriverWorkarounds(); /* Set this context as current */ - CORRADE_ASSERT(!_current, "Context: Another context currently active", false); - _current = this; + CORRADE_ASSERT(!currentContext, "Context: Another context currently active", false); + currentContext = this; + + /* Decide whether to print the initialization output or not */ + std::ostream* output = _displayInitializationLog ? &std::cout : nullptr; /* Print some info and initialize state tracker (which also prints some more info) */ - Debug() << "Renderer:" << rendererString() << "by" << vendorString(); - Debug() << "OpenGL version:" << versionString(); + Debug{output} << "Renderer:" << rendererString() << "by" << vendorString(); + Debug{output} << "OpenGL version:" << versionString(); /* Disable extensions as requested by the user */ if(!_disabledExtensions.empty()) { - Debug() << "Disabling extensions:"; + Debug{output} << "Disabling extensions:"; /* Put remaining extensions into the hashmap for faster lookup */ std::unordered_map allExtensions{std::move(futureExtensions)}; @@ -664,17 +685,17 @@ bool Context::tryCreate() { if(found == allExtensions.end()) continue; _extensionRequiredVersion[found->second._index] = Version::None; - Debug() << " " << extension; + Debug{output} << " " << extension; } } - _state = new Implementation::State(*this); + _state = new Implementation::State{*this, output}; /* Print a list of used workarounds */ if(!_driverWorkarounds.empty()) { - Debug() << "Using driver workarounds:"; + Debug{output} << "Using driver workarounds:"; for(const auto& workaround: _driverWorkarounds) - if(!workaround.second) Debug() << " " << workaround.first; + if(!workaround.second) Debug(output) << " " << workaround.first; } /* Initialize functionality based on current OpenGL version and extensions */ @@ -810,6 +831,7 @@ void Context::resetState(const States states) { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const Context::Flag value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Context::Flag::value: return debug << "Context::Flag::" #value; _c(Debug) _c(NoError) @@ -817,9 +839,10 @@ Debug& operator<<(Debug& debug, const Context::Flag value) { _c(RobustAccess) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Context::Flag::(invalid)"; + return debug << "Context::Flag(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } #endif #endif diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index 8ce3b2521..cacc5e740 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -244,6 +244,8 @@ class MAGNUM_EXPORT Context { /** * @brief Whether there is any current context * + * If Magnum is built with @ref MAGNUM_BUILD_MULTITHREADED, current + * context is thread-local instead of global (the default). * @see @ref current() */ static bool hasCurrent(); @@ -251,7 +253,9 @@ class MAGNUM_EXPORT Context { /** * @brief Current context * - * Expect that there is current context. + * Expect that there is current context. If Magnum is built with + * @ref MAGNUM_BUILD_MULTITHREADED, current context is thread-local + * instead of global (the default). * @see @ref hasCurrent() */ static Context& current(); @@ -501,9 +505,7 @@ class MAGNUM_EXPORT Context { Implementation::State& state() { return *_state; } private: - MAGNUM_LOCAL static Context* _current; - - explicit Context(NoCreateT, Int argc, char** argv, void functionLoader()); + explicit Context(NoCreateT, Int argc, const char** argv, void functionLoader()); bool tryCreate(); void create(); @@ -529,6 +531,7 @@ class MAGNUM_EXPORT Context { /* True means known and disabled, false means known */ std::vector> _driverWorkarounds; std::vector _disabledExtensions; + bool _displayInitializationLog; }; CORRADE_ENUMSET_OPERATORS(Context::DetectedDrivers) diff --git a/src/Magnum/DebugOutput.cpp b/src/Magnum/DebugOutput.cpp index f6cfe733e..d49b6db06 100644 --- a/src/Magnum/DebugOutput.cpp +++ b/src/Magnum/DebugOutput.cpp @@ -184,7 +184,7 @@ void DebugOutput::controlImplementationKhr(const GLenum source, const GLenum typ static_cast(severity); static_cast(ids); static_cast(enabled); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -206,7 +206,7 @@ void DebugOutput::callbackImplementationKhr(const Callback callback, const void* (callbackWrapper, userParam); #else static_cast(userParam); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif /* Deleting callback */ @@ -219,7 +219,7 @@ void DebugOutput::callbackImplementationKhr(const Callback callback, const void* #endif (nullptr, nullptr); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } } @@ -227,6 +227,7 @@ void DebugOutput::callbackImplementationKhr(const Callback callback, const void* #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const DebugOutput::Source value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case DebugOutput::Source::value: return debug << "DebugOutput::Source::" #value; _c(Api) _c(WindowSystem) @@ -235,13 +236,15 @@ Debug& operator<<(Debug& debug, const DebugOutput::Source value) { _c(Application) _c(Other) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "DebugOutput::Source::(invalid)"; + return debug << "DebugOutput::Source(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const DebugOutput::Type value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case DebugOutput::Type::value: return debug << "DebugOutput::Type::" #value; _c(Error) _c(DeprecatedBehavior) @@ -253,9 +256,10 @@ Debug& operator<<(Debug& debug, const DebugOutput::Type value) { _c(PopGroup) _c(Other) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "DebugOutput::Type::(invalid)"; + return debug << "DebugOutput::Type(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const DebugOutput::Severity value) { @@ -268,7 +272,7 @@ Debug& operator<<(Debug& debug, const DebugOutput::Severity value) { #undef _c } - return debug << "DebugOutput::Severity::(invalid)"; + return debug << "DebugOutput::Severity(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif @@ -292,7 +296,7 @@ void DebugMessage::insertImplementationKhr(const Source source, const Type type, static_cast(id); static_cast(severity); static_cast(string); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -301,7 +305,7 @@ void DebugMessage::insertImplementationExt(Source, Type, UnsignedInt, DebugOutpu glInsertEventMarkerEXT(string.size(), string.data()); #else static_cast(string); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -314,20 +318,29 @@ void DebugMessage::insertImplementationGremedy(Source, Type, UnsignedInt, DebugO #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const DebugMessage::Source value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case DebugMessage::Source::value: return debug << "DebugMessage::Source::" #value; _c(ThirdParty) _c(Application) #undef _c #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif case DebugMessage::Source::Api: case DebugMessage::Source::WindowSystem: case DebugMessage::Source::ShaderCompiler: case DebugMessage::Source::Other: return debug << DebugOutput::Source(value); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif + /* LCOV_EXCL_STOP */ } - return debug << "DebugMessage::Source::(invalid)"; + return debug << "DebugMessage::Source(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const DebugMessage::Type value) { @@ -343,7 +356,7 @@ Debug& operator<<(Debug& debug, const DebugMessage::Type value) { #undef _c } - return debug << "DebugMessage::Type::(invalid)"; + return debug << "DebugMessage::Type(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif @@ -390,7 +403,7 @@ void DebugGroup::pushImplementationKhr(const Source source, const UnsignedInt id static_cast(source); static_cast(id); static_cast(message); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -399,7 +412,7 @@ void DebugGroup::pushImplementationExt(Source, UnsignedInt, const Containers::Ar glPushGroupMarkerEXT(message.size(), message.data()); #else static_cast(message); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -411,7 +424,7 @@ void DebugGroup::popImplementationKhr() { #elif !defined(CORRADE_TARGET_NACL) glPopDebugGroupKHR(); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -419,20 +432,22 @@ void DebugGroup::popImplementationExt() { #ifndef CORRADE_TARGET_NACL glPopGroupMarkerEXT(); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const DebugGroup::Source value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case DebugGroup::Source::value: return debug << "DebugGroup::Source::" #value; _c(ThirdParty) _c(Application) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "DebugGroup::Source::(invalid)"; + return debug << "DebugGroup::Source(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/DebugOutput.h b/src/Magnum/DebugOutput.h index aa16b0c77..5842c618e 100644 --- a/src/Magnum/DebugOutput.h +++ b/src/Magnum/DebugOutput.h @@ -480,17 +480,17 @@ class MAGNUM_EXPORT DebugMessage { /** @copydoc DebugOutput::Source::Api * @deprecated Use @ref DebugOutput::Source::Api instead. */ - Api = GLenum(DebugOutput::Source::Api), + Api CORRADE_DEPRECATED_ENUM("use DebugOutput::Source::Api instead") = GLenum(DebugOutput::Source::Api), /** @copydoc DebugOutput::Source::WindowSystem * @deprecated Use @ref DebugOutput::Source::WindowSystem instead. */ - WindowSystem = GLenum(DebugOutput::Source::WindowSystem), + WindowSystem CORRADE_DEPRECATED_ENUM("use DebugOutput::Source::WindowSystem instead") = GLenum(DebugOutput::Source::WindowSystem), /** @copydoc DebugOutput::Source::ShaderCompiler * @deprecated Use @ref DebugOutput::Source::ShaderCompiler instead. */ - ShaderCompiler = GLenum(DebugOutput::Source::ShaderCompiler), + ShaderCompiler CORRADE_DEPRECATED_ENUM("use DebugOutput::Source::ShaderCompiler instead") = GLenum(DebugOutput::Source::ShaderCompiler), #endif /** External debugger or third-party middleware */ @@ -511,7 +511,7 @@ class MAGNUM_EXPORT DebugMessage { /** @copydoc DebugOutput::Source::Other * @deprecated Use @ref DebugOutput::Source::Other instead. */ - Other = GLenum(DebugOutput::Source::Other) + Other CORRADE_DEPRECATED_ENUM("use DebugOutput::Source::Other instead") = GLenum(DebugOutput::Source::Other) #endif }; @@ -581,7 +581,7 @@ class MAGNUM_EXPORT DebugMessage { * @deprecated Use @ref DebugOutput::Callback instead. */ /* Can't mark this as deprecated because compiler then complains when I use it as a parameter in setCallback() */ - typedef void(*Callback)(DebugMessage::Source, DebugMessage::Type, UnsignedInt, DebugOutput::Severity, const std::string&, const void*); + typedef CORRADE_DEPRECATED("use DebugOutput::Callback instead") void(*Callback)(DebugMessage::Source, DebugMessage::Type, UnsignedInt, DebugOutput::Severity, const std::string&, const void*); /** @copybrief DebugOutput::maxLoggedMessages() * @deprecated Use @ref DebugOutput::maxLoggedMessages() instead. @@ -635,7 +635,7 @@ class MAGNUM_EXPORT DebugMessage { /** @copybrief DebugOutput::setCallback() * @deprecated Use @ref DebugOutput::setCallback() instead. */ - CORRADE_DEPRECATED("use DebugOutput::setCallback() instead") static void setCallback(Callback callback, const void* userParam = nullptr) { + CORRADE_DEPRECATED("use DebugOutput::setCallback() instead") static void setCallback(DebugOutput::Callback callback, const void* userParam = nullptr) { DebugOutput::setCallback(reinterpret_cast(callback), userParam); } diff --git a/src/Magnum/DebugTools/Test/ForceRendererTest.cpp b/src/Magnum/DebugTools/Test/ForceRendererTest.cpp index 2d4a0c7a3..8206b76f6 100644 --- a/src/Magnum/DebugTools/Test/ForceRendererTest.cpp +++ b/src/Magnum/DebugTools/Test/ForceRendererTest.cpp @@ -24,6 +24,7 @@ */ #include +#include #include "../Implementation/ForceRendererTransformation.h" @@ -100,9 +101,18 @@ void ForceRendererTest::arbitrary3D() { /* All vectors are orthogonal */ CORRADE_COMPARE(Math::dot(m.right(), m.up()), 0.0f); + #ifndef CORRADE_TARGET_EMSCRIPTEN CORRADE_COMPARE(Math::dot(m.right(), m.backward()), 0.0f); + #else + /* Emscripten -O1 has slightly lower precision. -O2 works fine. */ + CORRADE_COMPARE_AS(Math::abs(Math::dot(m.right(), m.backward())), + Math::TypeTraits::epsilon(), + TestSuite::Compare::Less); + #endif /** @todo This shouldn't be too different */ - CORRADE_VERIFY(Math::abs(Math::dot(m.up(), m.backward())) < Math::TypeTraits::epsilon()); + CORRADE_COMPARE_AS(Math::abs(Math::dot(m.up(), m.backward())), + Math::TypeTraits::epsilon(), + TestSuite::Compare::Less); } }}}} diff --git a/src/Magnum/DefaultFramebuffer.cpp b/src/Magnum/DefaultFramebuffer.cpp index c8a148676..5129efb6b 100644 --- a/src/Magnum/DefaultFramebuffer.cpp +++ b/src/Magnum/DefaultFramebuffer.cpp @@ -117,15 +117,17 @@ void DefaultFramebuffer::initializeContextBasedFunctionality(Context& context) { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const DefaultFramebuffer::Status value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case DefaultFramebuffer::Status::value: return debug << "DefaultFramebuffer::Status::" #value; _c(Complete) #ifndef MAGNUM_TARGET_WEBGL _c(Undefined) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "DefaultFramebuffer::Status::(invalid)"; + return debug << "DefaultFramebuffer::Status(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/DimensionTraits.h b/src/Magnum/DimensionTraits.h index 7795fedd9..b0444c833 100644 --- a/src/Magnum/DimensionTraits.h +++ b/src/Magnum/DimensionTraits.h @@ -118,7 +118,6 @@ template<> struct DimensionTraits<2, Float> { typedef Math::Range2D RangeType; typedef Math::Matrix3 MatrixType; }; -#ifndef MAGNUM_TARGET_GLES template<> struct DimensionTraits<2, Double> { DimensionTraits() = delete; @@ -126,7 +125,6 @@ template<> struct DimensionTraits<2, Double> { typedef Math::Range2D RangeType; typedef Math::Matrix3 MatrixType; }; -#endif /* Three dimensions - integral */ template struct DimensionTraits<3, T> { @@ -144,7 +142,6 @@ template<> struct DimensionTraits<3, Float> { typedef Math::Range3D RangeType; typedef Math::Matrix4 MatrixType; }; -#ifndef MAGNUM_TARGET_GLES template<> struct DimensionTraits<3, Double> { DimensionTraits() = delete; @@ -153,7 +150,6 @@ template<> struct DimensionTraits<3, Double> { typedef Math::Matrix4 MatrixType; }; #endif -#endif } diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index a9ef8042f..71328fd4e 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -80,6 +80,7 @@ namespace GL { #ifndef MAGNUM_TARGET_GLES #line 1 namespace AMD { + _extension(GL,AMD,transform_feedback3_lines_triangles, GL210, None) // #397 _extension(GL,AMD,vertex_shader_layer, GL210, None) // #417 _extension(GL,AMD,shader_trinary_minmax, GL210, None) // #428 } namespace ARB { @@ -265,6 +266,7 @@ namespace GL { _extension(GL,OES,element_index_uint, GLES200, GLES300) // #10 _extension(GL,OES,texture_float_linear, GLES200, GLES300) // #20 _extension(GL,OES,texture_half_float_linear, GLES200, GLES300) // #21 + _extension(GL,OES,fbo_render_mipmap, GLES200, GLES300) // #28 #endif } namespace WEBGL { #ifdef MAGNUM_TARGET_GLES2 @@ -407,6 +409,7 @@ namespace GL { _extension(GL,OES,depth32, GLES200, None) // #25 #ifdef MAGNUM_TARGET_GLES2 _extension(GL,OES,element_index_uint, GLES200, GLES300) // #26 + _extension(GL,OES,fbo_render_mipmap, GLES200, GLES300) // #27 #endif _extension(GL,OES,mapbuffer, GLES200, None) // #29 #ifdef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index 096e47620..f17245fb4 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -389,7 +389,7 @@ void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment, static_cast(textureId); static_cast(mipLevel); static_cast(layer); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -408,6 +408,7 @@ void Framebuffer::textureLayerImplementationDSAEXT(BufferAttachment attachment, #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const Framebuffer::Status value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Framebuffer::Status::value: return debug << "Framebuffer::Status::" #value; _c(Complete) _c(IncompleteAttachment) @@ -424,9 +425,10 @@ Debug& operator<<(Debug& debug, const Framebuffer::Status value) { _c(IncompleteLayerTargets) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Framebuffer::Status::(invalid)"; + return debug << "Framebuffer::Status(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 196fa63d3..d6fad0949 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -149,7 +149,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in * WebGL 1.0. */ - class DrawAttachment { + class MAGNUM_EXPORT DrawAttachment { public: /** @brief No attachment */ static const DrawAttachment None; @@ -621,6 +621,10 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}, * eventually @fn_gl{BindFramebuffer} and * @fn_gl2{FramebufferTexture2D,FramebufferTexture} + * @requires_gles30 Extension @es_extension{OES,fbo_render_mipmap} to + * render to @p level different than `0` in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{OES,fbo_render_mipmap} + * to render to @p level different than `0` in WebGL 1.0. */ Framebuffer& attachTexture(BufferAttachment attachment, Texture2D& texture, Int level); @@ -659,6 +663,10 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @fn_gl2{NamedFramebufferTextureLayer,FramebufferTextureLayer}, * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}, * eventually @fn_gl{BindFramebuffer} and @fn_gl2{FramebufferTexture2D,FramebufferTexture} + * @requires_gles30 Extension @es_extension{OES,fbo_render_mipmap} to + * render to @p level different than `0` in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{OES,fbo_render_mipmap} + * to render to @p level different than `0` in WebGL 1.0. */ Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapCoordinate coordinate, Int level); @@ -682,6 +690,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * OpenGL ES 2.0 * @requires_gles30 Extension @es_extension{OES,texture_3D} in OpenGL * ES 2.0. + * @requires_gles30 Extension @es_extension{OES,fbo_render_mipmap} to + * render to @p level different than `0` in OpenGL ES 2.0. * @requires_webgl20 Only 2D textures are available in WebGL 1.0. */ Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture3D& texture, Int level, Int layer); diff --git a/src/Magnum/Image.cpp b/src/Magnum/Image.cpp index 98c9cadf3..163ba5640 100644 --- a/src/Magnum/Image.cpp +++ b/src/Magnum/Image.cpp @@ -27,7 +27,7 @@ namespace Magnum { -template Image::Image(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data): _storage{storage}, _format{format}, _type{type}, _size{size}, _data{std::move(data)} { +template Image::Image(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data) noexcept: _storage{storage}, _format{format}, _type{type}, _size{size}, _data{std::move(data)} { CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Image::Image(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); } diff --git a/src/Magnum/Image.h b/src/Magnum/Image.h index f5af9a50b..a725c83ed 100644 --- a/src/Magnum/Image.h +++ b/src/Magnum/Image.h @@ -59,19 +59,24 @@ template class Image { * The data are expected to be of proper size for given @p storage * parameters. */ - explicit Image(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data); + explicit Image(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data) noexcept; /** @overload * Similar to the above, but uses default @ref PixelStorage parameters. */ - explicit Image(PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data): Image{{}, format, type, size, std::move(data)} {} + explicit Image(PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data) noexcept: Image{{}, format, type, size, std::move(data)} {} #ifdef MAGNUM_BUILD_DEPRECATED /** @copybrief Image(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&) * @deprecated Use @ref Image(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&) * instead. */ - explicit CORRADE_DEPRECATED("use Image(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&) instead") Image(PixelFormat format, PixelType type, const VectorTypeFor& size, void* data): Image{{}, format, type, size, Containers::Array{reinterpret_cast(data), Implementation::imageDataSizeFor(format, type, size)}} {} + explicit CORRADE_DEPRECATED("use Image(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&) instead") Image(PixelFormat format, PixelType type, const VectorTypeFor& size, void* data) noexcept: Image{{}, format, type, size, Containers::Array{reinterpret_cast(data), Implementation::imageDataSizeFor(format, type, size)}} {} + #ifndef DOXYGEN_GENERATING_OUTPUT + /* To avoid decay of nullptr to const void* and unwanted use of + deprecated function */ + explicit Image(PixelFormat format, PixelType type, const VectorTypeFor& size, std::nullptr_t) noexcept: Image{{}, format, type, size, nullptr} {} + #endif #endif /** @@ -87,12 +92,12 @@ template class Image { * @ref AbstractFramebuffer::read() "*Framebuffer::read()" to fill the * image with data using @p storage settings. */ - /*implicit*/ Image(PixelStorage storage, PixelFormat format, PixelType type): _storage{storage}, _format{format}, _type{type}, _data{} {} + /*implicit*/ Image(PixelStorage storage, PixelFormat format, PixelType type) noexcept: _storage{storage}, _format{format}, _type{type}, _data{} {} /** @overload * Similar to the above, but uses default @ref PixelStorage parameters. */ - /*implicit*/ Image(PixelFormat format, PixelType type): Image{{}, format, type} {} + /*implicit*/ Image(PixelFormat format, PixelType type) noexcept: Image{{}, format, type} {} /** @brief Copying is not allowed */ Image(const Image&) = delete; @@ -135,7 +140,7 @@ template class Image { * * See @ref PixelStorage::dataProperties() for more information. */ - std::tuple, std::size_t> dataProperties() const { + std::tuple, VectorTypeFor, std::size_t> dataProperties() const { return Implementation::imageDataProperties(*this); } @@ -144,10 +149,24 @@ template class Image { * * @see @ref release() */ - Containers::ArrayView data() { return _data; } + Containers::ArrayView data() + #ifndef CORRADE_GCC47_COMPATIBILITY + & + #endif + { return _data; } + #ifndef CORRADE_GCC47_COMPATIBILITY + Containers::ArrayView data() && = delete; /**< @overload */ + #endif /** @overload */ - Containers::ArrayView data() const { return _data; } + Containers::ArrayView data() const + #ifndef CORRADE_GCC47_COMPATIBILITY + & + #endif + { return _data; } + #ifndef CORRADE_GCC47_COMPATIBILITY + Containers::ArrayView data() const && = delete; /**< @overload */ + #endif /** @overload */ template T* data() { @@ -325,7 +344,7 @@ template class CompressedImage { * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * WebGL. */ - std::tuple, std::size_t> dataProperties() const { + std::tuple, VectorTypeFor, std::size_t> dataProperties() const { return Implementation::compressedImageDataProperties(*this); } #endif diff --git a/src/Magnum/ImageView.h b/src/Magnum/ImageView.h index cdc5067f4..bf26109ce 100644 --- a/src/Magnum/ImageView.h +++ b/src/Magnum/ImageView.h @@ -35,6 +35,10 @@ #include "Magnum/PixelStorage.h" #include "Magnum/Math/Vector4.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif + namespace Magnum { /** @@ -86,6 +90,10 @@ template class ImageView { explicit CORRADE_DEPRECATED("use ImageView(PixelFormat, PixelType, const VectorTypeFor&, Containers::ArrayView) instead") ImageView(PixelFormat format, PixelType type, const VectorTypeFor& size, const void* data) noexcept: ImageView{{}, format, type, size, {reinterpret_cast(data), Implementation::imageDataSizeFor(format, type, size)}} {} #ifndef DOXYGEN_GENERATING_OUTPUT + /* To avoid ambiguous overload when passing ArrayView to the + constructor */ + template explicit ImageView(PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::ArrayView data): ImageView{{}, format, type, size, Containers::ArrayView{data}} {} + template explicit ImageView(PixelFormat format, PixelType type, const VectorTypeFor& size, const Containers::Array& data): ImageView{{}, format, type, size, Containers::ArrayView(data)} {} /* To avoid decay of sized arrays and nullptr to const void* and unwanted use of deprecated function */ template explicit ImageView(PixelFormat format, PixelType type, const VectorTypeFor& size, const T(&data)[dataSize]): ImageView{{}, format, type, size, Containers::ArrayView{data}} {} @@ -134,7 +142,7 @@ template class ImageView { * * See @ref PixelStorage::dataProperties() for more information. */ - std::tuple, std::size_t> dataProperties() const { + std::tuple, VectorTypeFor, std::size_t> dataProperties() const { return Implementation::imageDataProperties(*this); } @@ -169,6 +177,14 @@ template class ImageView { } #ifndef DOXYGEN_GENERATING_OUTPUT + /* To avoid ambiguous overload when passing ArrayView to the + function */ + template void setData(Containers::ArrayView data) { + setData(Containers::ArrayView{data}); + } + template void setData(const Containers::Array& data) { + setData(Containers::ArrayView(data)); + } /* To avoid decay of sized arrays and nullptr to const void* and unwanted use of deprecated function */ template void setData(const T(&data)[size]) { diff --git a/src/Magnum/Implementation/BufferState.cpp b/src/Magnum/Implementation/BufferState.cpp index a4181ab19..f76d4dff4 100644 --- a/src/Magnum/Implementation/BufferState.cpp +++ b/src/Magnum/Implementation/BufferState.cpp @@ -79,7 +79,7 @@ std::size_t BufferState::indexForTarget(Buffer::TargetHint target) { #endif } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } BufferState::BufferState(Context& context, std::vector& extensions): bindings() diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp index 9ba1004f5..d0ebb0a57 100644 --- a/src/Magnum/Implementation/FramebufferState.cpp +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -68,6 +68,11 @@ FramebufferState::FramebufferState(Context& context, std::vector& e drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA; readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; + copySub1DImplementation = &AbstractFramebuffer::copySub1DImplementationDSA; + copySub2DImplementation = &AbstractFramebuffer::copySub2DImplementationDSA; + copySubCubeMapImplementation = &AbstractFramebuffer::copySubCubeMapImplementationDSA; + copySub3DImplementation = &AbstractFramebuffer::copySub3DImplementationDSA; + renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; /* The 1D implementation uses the same function as the layered attachment */ texture1DImplementation = &Framebuffer::textureImplementationDSA; @@ -88,6 +93,11 @@ FramebufferState::FramebufferState(Context& context, std::vector& e drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSAEXT; readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSAEXT; + copySub1DImplementation = &AbstractFramebuffer::copySub1DImplementationDSAEXT; + copySub2DImplementation = &AbstractFramebuffer::copySub2DImplementationDSAEXT; + copySubCubeMapImplementation = &AbstractFramebuffer::copySub2DImplementationDSAEXT; + copySub3DImplementation = &AbstractFramebuffer::copySub3DImplementationDSAEXT; + renderbufferImplementation = &Framebuffer::renderbufferImplementationDSAEXT; texture1DImplementation = &Framebuffer::texture1DImplementationDSAEXT; /* The EXT_DSA implementation is the same for both 2D and cube map textures */ @@ -111,6 +121,15 @@ FramebufferState::FramebufferState(Context& context, std::vector& e readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault; #endif + #ifndef MAGNUM_TARGET_GLES + copySub1DImplementation = &AbstractFramebuffer::copySub1DImplementationDefault; + #endif + copySub2DImplementation = &AbstractFramebuffer::copySub2DImplementationDefault; + copySubCubeMapImplementation = &AbstractFramebuffer::copySub2DImplementationDefault; + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + copySub3DImplementation = &AbstractFramebuffer::copySub3DImplementationDefault; + #endif + renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault; #ifndef MAGNUM_TARGET_GLES texture1DImplementation = &Framebuffer::texture1DImplementationDefault; diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index 278f87d6b..57564b103 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -56,6 +56,16 @@ struct FramebufferState { #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void(AbstractFramebuffer::*readBufferImplementation)(GLenum); + #endif + #ifndef MAGNUM_TARGET_GLES + void(*copySub1DImplementation)(const Range2Di&, AbstractTexture&, Int, Int); + #endif + void(*copySub2DImplementation)(const Range2Di&, AbstractTexture&, GLenum, Int, const Vector2i&); + void(*copySubCubeMapImplementation)(const Range2Di&, AbstractTexture&, GLenum, Int, const Vector2i&); + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + void(*copySub3DImplementation)(const Range2Di&, AbstractTexture&, Int, const Vector3i&); + #endif + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void(AbstractFramebuffer::*invalidateImplementation)(GLsizei, const GLenum*); #endif #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/Implementation/ShaderProgramState.cpp b/src/Magnum/Implementation/ShaderProgramState.cpp index 2d16fa201..80e753a8b 100644 --- a/src/Magnum/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/Implementation/ShaderProgramState.cpp @@ -47,6 +47,19 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector()) diff --git a/src/Magnum/Implementation/ShaderProgramState.h b/src/Magnum/Implementation/ShaderProgramState.h index 689875174..92aa939a2 100644 --- a/src/Magnum/Implementation/ShaderProgramState.h +++ b/src/Magnum/Implementation/ShaderProgramState.h @@ -32,10 +32,7 @@ #include "Magnum/OpenGL.h" #include "Magnum/Math/Vector3.h" -#ifdef _MSC_VER -/* Otherwise the member function pointers will have different size based on - whether the header was included or not. CAUSES SERIOUS MEMORY CORRUPTION AND - IS NOT CAUGHT BY ANY WARNING WHATSOEVER! AARGH! */ +#ifndef MAGNUM_TARGET_GLES2 #include "Magnum/AbstractShaderProgram.h" #endif @@ -46,6 +43,10 @@ struct ShaderProgramState { void reset(); + #ifndef MAGNUM_TARGET_GLES2 + void(AbstractShaderProgram::*transformFeedbackVaryingsImplementation)(Containers::ArrayView, AbstractShaderProgram::TransformFeedbackBufferMode); + #endif + void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*); void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*); void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*); diff --git a/src/Magnum/Implementation/State.cpp b/src/Magnum/Implementation/State.cpp index 3b14cbd06..aec634451 100644 --- a/src/Magnum/Implementation/State.cpp +++ b/src/Magnum/Implementation/State.cpp @@ -49,7 +49,7 @@ namespace Magnum { namespace Implementation { -State::State(Context& context) { +State::State(Context& context, std::ostream* const out) { /* List of extensions used in current context. Guesstimate count to avoid unnecessary reallocations. */ std::vector extensions; @@ -80,8 +80,8 @@ State::State(Context& context) { std::sort(extensions.begin(), extensions.end()); extensions.erase(std::unique(extensions.begin(), extensions.end()), extensions.end()); - Debug() << "Using optional features:"; - for(const auto& ext: extensions) Debug() << " " << ext; + Debug{out} << "Using optional features:"; + for(const auto& ext: extensions) Debug(out) << " " << ext; } State::~State() = default; diff --git a/src/Magnum/Implementation/State.h b/src/Magnum/Implementation/State.h index 1975ba37c..4ff17793b 100644 --- a/src/Magnum/Implementation/State.h +++ b/src/Magnum/Implementation/State.h @@ -51,7 +51,7 @@ struct TransformFeedbackState; struct State { /* Initializes context-based functionality */ - explicit State(Context& context); + explicit State(Context& context, std::ostream* out); ~State(); diff --git a/src/Magnum/Implementation/TransformFeedbackState.cpp b/src/Magnum/Implementation/TransformFeedbackState.cpp index 020269ab8..4484cb837 100644 --- a/src/Magnum/Implementation/TransformFeedbackState.cpp +++ b/src/Magnum/Implementation/TransformFeedbackState.cpp @@ -10,7 +10,7 @@ namespace Magnum { namespace Implementation { TransformFeedbackState::TransformFeedbackState(Context& context, std::vector& extensions): maxInterleavedComponents{0}, maxSeparateAttributes{0}, maxSeparateComponents{0} #ifndef MAGNUM_TARGET_GLES - , maxBuffers{0} + , maxBuffers{0}, maxVertexStreams{0} #endif { #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Implementation/TransformFeedbackState.h b/src/Magnum/Implementation/TransformFeedbackState.h index 93047d51a..e9cd227c6 100644 --- a/src/Magnum/Implementation/TransformFeedbackState.h +++ b/src/Magnum/Implementation/TransformFeedbackState.h @@ -53,7 +53,8 @@ struct TransformFeedbackState { maxSeparateAttributes, maxSeparateComponents; #ifndef MAGNUM_TARGET_GLES - GLint maxBuffers; + GLint maxBuffers, + maxVertexStreams; #endif GLuint binding; diff --git a/src/Magnum/Implementation/driverSpecific.cpp b/src/Magnum/Implementation/driverSpecific.cpp index e6840aeda..060d5f2d4 100644 --- a/src/Magnum/Implementation/driverSpecific.cpp +++ b/src/Magnum/Implementation/driverSpecific.cpp @@ -34,19 +34,32 @@ namespace Magnum { namespace { std::vector KnownWorkarounds{ - #ifndef MAGNUM_TARGET_GLES + #if !defined(MAGNUM_TARGET_GLES) && !defined(CORRADE_TARGET_APPLE) /* Creating core context with specific version on AMD and NV - proprietary drivers causes the context to be forced to given - version instead of selecting latest available version */ - "amd-nv-no-forward-compatible-core-context", + proprietary drivers on Linux/Windows and Intel drivers on Windows + causes the context to be forced to given version instead of + selecting latest available version */ + "no-forward-compatible-core-context", + #endif - #ifdef CORRADE_TARGET_WINDOWS + #if !defined(MAGNUM_TARGET_GLES) && defined(CORRADE_TARGET_WINDOWS) /* On Windows Intel drivers ARB_shading_language_420pack is exposed in GLSL even though the extension (e.g. binding keyword) is not supported */ "intel-windows-glsl-exposes-unsupported-shading-language-420pack", #endif + #if !defined(MAGNUM_TARGET_GLES2) && defined(CORRADE_TARGET_WINDOWS) + /* On Windows NVidia drivers the glTransformFeedbackVaryings() does not + make a copy of its char* arguments so it fails at link time when the + original char arrays are not in scope anymore. Enabling + *synchronous* debug output circumvents this bug. Can be triggered by + running TransformFeedbackGLTest with GL_KHR_debug extension + disabled. */ + "nv-windows-dangling-transform-feedback-varying-names", + #endif + + #if !defined(MAGNUM_TARGET_GLES) /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL 1.30 on NVidia and 1.40 on Mac OS X. Everything is fine when using newer GLSL version. */ diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index a55936625..d552ce546 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -50,10 +50,8 @@ namespace Math { #ifdef MAGNUM_BUILD_DEPRECATED namespace Literals { - #ifndef MAGNUM_TARGET_GLES constexpr Rad operator "" _rad(long double); constexpr Deg operator "" _deg(long double); - #endif constexpr Rad operator "" _radf(long double); constexpr Deg operator "" _degf(long double); } @@ -91,6 +89,16 @@ Defined if built as static libraries. Default are shared libraries. #define MAGNUM_BUILD_STATIC #undef MAGNUM_BUILD_STATIC +/** +@brief Multi-threaded build + +Defined if the library is built in a way that allows multiple thread-local +Magnum contexts. Enabled by default. +@see @ref building, @ref cmake, @ref Magnum::Context::current() "Context::current()" +*/ +#define MAGNUM_BUILD_MULTITHREADED +#undef MAGNUM_BUILD_MULTITHREADED + /** @brief OpenGL ES target @@ -294,6 +302,18 @@ typedef Math::Matrix3x4 Matrix3x4; /** @brief Float matrix with 4 columns and 3 rows */ typedef Math::Matrix4x3 Matrix4x3; +/** @brief Float two-dimensional quadratic Bézier curve */ +typedef Math::QuadraticBezier2D QuadraticBezier2D; + +/** @brief Float three-dimensional quadratic Bézier curve */ +typedef Math::QuadraticBezier3D QuadraticBezier3D; + +/** @brief Float two-dimensional cubic Bézier curve */ +typedef Math::CubicBezier2D CubicBezier2D; + +/** @brief Float three-dimensional cubic Bézier curve */ +typedef Math::CubicBezier3D CubicBezier3D; + /** @brief Float complex number */ typedef Math::Complex Complex; @@ -335,11 +355,9 @@ typedef Math::Range3D Range3Di; /*@}*/ -#ifndef MAGNUM_TARGET_GLES /** @{ @name Double-precision types See @ref types for more information. -@requires_gl Only single-precision types are available in OpenGL ES and WebGL. */ /** @brief Double (64bit) */ @@ -405,6 +423,18 @@ typedef Math::Matrix3x4 Matrix3x4d; /** @brief Double matrix with 4 columns and 3 rows */ typedef Math::Matrix4x3 Matrix4x3d; +/** @brief Double two-dimensional quadratic Bézier curve */ +typedef Math::QuadraticBezier2D QuadraticBezier2Dd; + +/** @brief Double three-dimensional quadratic Bézier curve */ +typedef Math::QuadraticBezier3D QuadraticBezier3Dd; + +/** @brief Double two-dimensional cubic Bézier curve */ +typedef Math::CubicBezier2D CubicBezier2Dd; + +/** @brief Double three-dimensional cubic Bézier curve */ +typedef Math::CubicBezier3D CubicBezier3Dd; + /** @brief Double complex number */ typedef Math::Complex Complexd; @@ -436,13 +466,10 @@ typedef Math::Range2D Range2Dd; typedef Math::Range3D Range3Dd; /*@}*/ -#endif #ifdef MAGNUM_BUILD_DEPRECATED -#ifndef MAGNUM_TARGET_GLES using Math::Literals::operator "" _deg; using Math::Literals::operator "" _rad; -#endif using Math::Literals::operator "" _degf; using Math::Literals::operator "" _radf; #endif diff --git a/src/Magnum/Math/Algorithms/CMakeLists.txt b/src/Magnum/Math/Algorithms/CMakeLists.txt index 06c46f8bf..cfddc216e 100644 --- a/src/Magnum/Math/Algorithms/CMakeLists.txt +++ b/src/Magnum/Math/Algorithms/CMakeLists.txt @@ -26,6 +26,7 @@ set(MagnumMathAlgorithms_HEADERS GaussJordan.h GramSchmidt.h + Qr.h Svd.h) # Force IDEs to display all header files in project view diff --git a/src/Magnum/Math/Algorithms/GaussJordan.h b/src/Magnum/Math/Algorithms/GaussJordan.h index ac6ba4a8e..c5dfcb43a 100644 --- a/src/Magnum/Math/Algorithms/GaussJordan.h +++ b/src/Magnum/Math/Algorithms/GaussJordan.h @@ -26,10 +26,10 @@ */ /** @file - * @brief Function @ref Magnum::Math::Algorithms::gaussJordanInPlaceTransposed(), @ref Magnum::Math::Algorithms::gaussJordanInPlace() + * @brief Function @ref Magnum::Math::Algorithms::gaussJordanInPlaceTransposed(), @ref Magnum::Math::Algorithms::gaussJordanInPlace(), @ref Magnum::Math::Algorithms::gaussJordanInverted() */ -#include "Magnum/Math/RectangularMatrix.h" +#include "Magnum/Math/Matrix.h" namespace Magnum { namespace Math { namespace Algorithms { @@ -111,6 +111,20 @@ template bool gaussJordanInPlace(Re return ret; } +/** +@brief Gauss-Jordan matrix inversion + +Since @f$ (\boldsymbol{A}^{-1})^T = (\boldsymbol{A}^T)^{-1} @f$, passes @p a +and an identity matrix to @ref gaussJordanInPlaceTransposed() and returns the +inverted matrix. Expects that the matrix is invertible. +@see @ref Matrix::inverted() +*/ +template Matrix gaussJordanInverted(Matrix matrix) { + Matrix inverted{Math::IdentityInit}; + CORRADE_INTERNAL_ASSERT_OUTPUT(gaussJordanInPlaceTransposed(matrix, inverted)); + return inverted; +} + }}} #endif diff --git a/src/Magnum/Math/Algorithms/Qr.h b/src/Magnum/Math/Algorithms/Qr.h new file mode 100644 index 000000000..7ddfe91b4 --- /dev/null +++ b/src/Magnum/Math/Algorithms/Qr.h @@ -0,0 +1,59 @@ +#ifndef Magnum_Math_Algorithms_Qr_h +#define Magnum_Math_Algorithms_Qr_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Function @ref Magnum::Math::Algorithms::qr() + */ + +#include "Magnum/Math/Matrix.h" + +namespace Magnum { namespace Math { namespace Algorithms { + +/** +@brief QR decomposition + +Calculated using classic Gram-Schmidt process. +*/ +template std::pair, Matrix> qr(const Matrix& matrix) { + Matrix q, r; + + for(std::size_t k = 0; k != size; ++k) { + Vector p = matrix[k]; + for(std::size_t j = 0; j != k; ++j) { + r[k][j] = Math::dot(p, q[j]); + p -= q[j]*r[k][j]; + } + r[k][k] = p.length(); + q[k] = p/r[k][k]; + } + + return {q, r}; +} + +}}} + +#endif diff --git a/src/Magnum/Math/Algorithms/Svd.h b/src/Magnum/Math/Algorithms/Svd.h index 514a4f274..65d35b9b5 100644 --- a/src/Magnum/Math/Algorithms/Svd.h +++ b/src/Magnum/Math/Algorithms/Svd.h @@ -51,9 +51,7 @@ template T pythagoras(T a, T b) { template constexpr T smallestDelta(); template<> constexpr Float smallestDelta() { return 1.0e-32f; } -#ifndef MAGNUM_TARGET_GLES template<> constexpr Double smallestDelta() { return 1.0e-64; } -#endif } diff --git a/src/Magnum/Math/Algorithms/Test/CMakeLists.txt b/src/Magnum/Math/Algorithms/Test/CMakeLists.txt index 5ab52b53b..926d21613 100644 --- a/src/Magnum/Math/Algorithms/Test/CMakeLists.txt +++ b/src/Magnum/Math/Algorithms/Test/CMakeLists.txt @@ -25,4 +25,5 @@ corrade_add_test(MathAlgorithmsGaussJordanTest GaussJordanTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathAlgorithmsGramSchmidtTest GramSchmidtTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathAlgorithmsQrTest QrTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathAlgorithmsSvdTest SvdTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Magnum/Math/Algorithms/Test/GaussJordanTest.cpp b/src/Magnum/Math/Algorithms/Test/GaussJordanTest.cpp index d7885d1b1..cb20424de 100644 --- a/src/Magnum/Math/Algorithms/Test/GaussJordanTest.cpp +++ b/src/Magnum/Math/Algorithms/Test/GaussJordanTest.cpp @@ -32,16 +32,38 @@ namespace Magnum { namespace Math { namespace Algorithms { namespace Test { struct GaussJordanTest: Corrade::TestSuite::Tester { explicit GaussJordanTest(); + void test(); void singular(); - void invert(); + void inverted(); }; -typedef RectangularMatrix<4, 4, Float> Matrix4x4; +typedef Matrix<4, Float> Matrix4x4; typedef Vector<4, Float> Vector4; GaussJordanTest::GaussJordanTest() { - addTests({&GaussJordanTest::singular, - &GaussJordanTest::invert}); + addTests({&GaussJordanTest::test, + &GaussJordanTest::singular, + &GaussJordanTest::inverted}); +} + +void GaussJordanTest::test() { + /* Basic matrix inversion */ + const Matrix4x4 m{Vector4{3.0f, 5.0f, 8.0f, 4.0f}, + Vector4{4.0f, 4.0f, 7.0f, 3.0f}, + Vector4{7.0f, -1.0f, 8.0f, 0.0f}, + Vector4{9.0f, 4.0f, 5.0f, 9.0f}}; + + const Matrix4x4 expected{Vector4{-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f}, + Vector4{-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f}, + Vector4{177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f}, + Vector4{259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f}}; + + Matrix4x4 a2{m}; + Matrix4x4 inverse{Math::IdentityInit}; + CORRADE_VERIFY(gaussJordanInPlace(a2, inverse)); + + CORRADE_COMPARE(inverse, expected); + CORRADE_COMPARE(m*inverse, Matrix4x4{}); } void GaussJordanTest::singular() { @@ -54,23 +76,20 @@ void GaussJordanTest::singular() { CORRADE_VERIFY(!gaussJordanInPlaceTransposed(a, t)); } -void GaussJordanTest::invert() { - Matrix4x4 a(Vector4(3.0f, 5.0f, 8.0f, 4.0f), - Vector4(4.0f, 4.0f, 7.0f, 3.0f), - Vector4(7.0f, -1.0f, 8.0f, 0.0f), - Vector4(9.0f, 4.0f, 5.0f, 9.0f)); +void GaussJordanTest::inverted() { + const Matrix4x4 m{Vector4{3.0f, 5.0f, 8.0f, 4.0f}, + Vector4{4.0f, 4.0f, 7.0f, 3.0f}, + Vector4{7.0f, -1.0f, 8.0f, 0.0f}, + Vector4{9.0f, 4.0f, 5.0f, 9.0f}}; - Matrix4x4 expectedInverse(Vector4(-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f), - Vector4(-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f), - Vector4(177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f), - Vector4(259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f)); - - Matrix4x4 a2(a); - Matrix4x4 inverse = Matrix4x4::fromDiagonal(Vector4(1.0f)); - CORRADE_VERIFY(gaussJordanInPlace(a2, inverse)); + const Matrix4x4 expected{Vector4{-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f}, + Vector4{-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f}, + Vector4{177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f}, + Vector4{259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f}}; - CORRADE_COMPARE(inverse, expectedInverse); - CORRADE_COMPARE(a*inverse, Matrix4x4::fromDiagonal(Vector4(1.0f))); + const Matrix4x4 inverse = gaussJordanInverted(m); + CORRADE_COMPARE(inverse, expected); + CORRADE_COMPARE(inverse*m, Matrix4x4{}); } }}}} diff --git a/src/Magnum/Math/Algorithms/Test/QrTest.cpp b/src/Magnum/Math/Algorithms/Test/QrTest.cpp new file mode 100644 index 000000000..272bfa466 --- /dev/null +++ b/src/Magnum/Math/Algorithms/Test/QrTest.cpp @@ -0,0 +1,69 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Magnum/Math/Matrix3.h" +#include "Magnum/Math/Algorithms/Qr.h" + +namespace Magnum { namespace Math { namespace Algorithms { namespace Test { + +struct QrTest: Corrade::TestSuite::Tester { + explicit QrTest(); + + void test(); +}; + +typedef Matrix3 Matrix3; + +QrTest::QrTest() { + addTests({&QrTest::test}); +} + +void QrTest::test() { + Matrix3 a{{ 0.0f, 3.0f, 4.0f}, + {-20.0f, 27.0f, 11.0f}, + {-14.0f, -4.0f, -2.0f}}; + + Matrix3 q, r; + std::tie(q, r) = Algorithms::qr(a); + + CORRADE_COMPARE(q*r, a); + + Matrix3 qExpected = Matrix3{{ 0.0f, 15.0f, 20.0f}, + {-20.0f, 12.0f, -9.0f}, + {-15.0f, -16.0f, 12.0f}}/25.0f; + CORRADE_COMPARE(q, qExpected); + + Matrix3 rExpected{{ 5.0f, 0.0f, 0.0f}, + {25.0f, 25.0f, 0.0f}, + {-4.0f, 10.0f, 10.0f}}; + CORRADE_COMPARE(r, rExpected); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Math::Algorithms::Test::QrTest) diff --git a/src/Magnum/Math/Algorithms/Test/SvdTest.cpp b/src/Magnum/Math/Algorithms/Test/SvdTest.cpp index 1651166d9..ee10b342a 100644 --- a/src/Magnum/Math/Algorithms/Test/SvdTest.cpp +++ b/src/Magnum/Math/Algorithms/Test/SvdTest.cpp @@ -32,89 +32,47 @@ namespace Magnum { namespace Math { namespace Algorithms { namespace Test { struct SvdTest: Corrade::TestSuite::Tester { explicit SvdTest(); - void testDouble(); - void testFloat(); + template void test(); }; -#ifndef MAGNUM_TARGET_GLES -typedef RectangularMatrix<5, 8, Double> Matrix5x8d; -typedef Matrix<8, Double> Matrix8d; -typedef Matrix<5, Double> Matrix5d; -typedef Vector<8, Double> Vector8d; -typedef Vector<5, Double> Vector5d; -#endif - -typedef RectangularMatrix<5, 8, Float> Matrix5x8f; -typedef Matrix<8, Float> Matrix8f; -typedef Matrix<5, Float> Matrix5f; -typedef Vector<8, Float> Vector8f; -typedef Vector<5, Float> Vector5f; - -#ifndef MAGNUM_TARGET_GLES -constexpr static Matrix5x8d ad( - Vector8d(22.0, 14.0, -1.0, -3.0, 9.0, 9.0, 2.0, 4.0), - Vector8d(10.0, 7.0, 13.0, -2.0, 8.0, 1.0, -6.0, 5.0), - Vector8d( 2.0, 10.0, -1.0, 13.0, 1.0, -7.0, 6.0, 0.0), - Vector8d( 3.0, 0.0, -11.0, -2.0, -2.0, 5.0, 5.0, -2.0), - Vector8d( 7.0, 8.0, 3.0, 4.0, 4.0, -1.0, 1.0, 2.0) -); -static const Vector5d expectedd(std::sqrt(1248.0), 0.0, 20.0, std::sqrt(384.0), 0.0); -#endif - -constexpr static Matrix5x8f af( - Vector8f(22.0f, 14.0f, -1.0f, -3.0f, 9.0f, 9.0f, 2.0f, 4.0f), - Vector8f(10.0f, 7.0f, 13.0f, -2.0f, 8.0f, 1.0f, -6.0f, 5.0f), - Vector8f( 2.0f, 10.0f, -1.0f, 13.0f, 1.0f, -7.0f, 6.0f, 0.0f), - Vector8f( 3.0f, 0.0f, -11.0f, -2.0f, -2.0f, 5.0f, 5.0f, -2.0f), - Vector8f( 7.0f, 8.0f, 3.0f, 4.0f, 4.0f, -1.0f, 1.0f, 2.0f) -); -static const Vector5f expectedf(std::sqrt(1248.0f), 0.0f, 20.0f, std::sqrt(384.0f), 0.0f); +template using Matrix5x8 = RectangularMatrix<5, 8, T>; +template using Matrix8 = Matrix<8, T>; +template using Matrix5 = Matrix<5, T>; +template using Vector8 = Vector<8, T>; +template using Vector5 = Vector<5, T>; SvdTest::SvdTest() { - addTests({&SvdTest::testDouble, - &SvdTest::testFloat}); + addTests({&SvdTest::test, + &SvdTest::test}); } -void SvdTest::testDouble() { - #ifndef MAGNUM_TARGET_GLES - Matrix5x8d u; - Vector5d w; - Matrix5d v; - std::tie(u, w, v) = Algorithms::svd(ad); +template void SvdTest::test() { + setTestCaseName(std::is_same::value ? "test" : "test"); - /* Test composition */ - Matrix8d u2(u[0], u[1], u[2], u[3], u[4], Vector8d(), Vector8d(), Vector8d()); - Matrix5x8d w2 = Matrix5x8d::fromDiagonal(w); - CORRADE_COMPARE(u2*w2*v.transposed(), ad); - - /* Test that V is unitary */ - CORRADE_COMPARE(v*v.transposed(), Matrix5d{IdentityInit}); - CORRADE_COMPARE(v.transposed()*v, Matrix5d{IdentityInit}); - - /* Test W */ - CORRADE_COMPARE(w, expectedd); - #else - CORRADE_SKIP("Double precision is not supported when targeting OpenGL ES."); - #endif -} + constexpr const Matrix5x8 a{ + Vector8{T{22}, T{14}, T{ -1}, T{-3}, T{ 9}, T{ 9}, T{ 2}, T{ 4}}, + Vector8{T{10}, T{ 7}, T{ 13}, T{-2}, T{ 8}, T{ 1}, T{-6}, T{ 5}}, + Vector8{T{ 2}, T{10}, T{ -1}, T{13}, T{ 1}, T{-7}, T{ 6}, T{ 0}}, + Vector8{T{ 3}, T{ 0}, T{-11}, T{-2}, T{-2}, T{ 5}, T{ 5}, T{-2}}, + Vector8{T{ 7}, T{ 8}, T{ 3}, T{ 4}, T{ 4}, T{-1}, T{ 1}, T{ 2}}}; + const Vector5 expected(std::sqrt(T{1248}), T{0}, T{20}, std::sqrt(T{384}), T{0}); -void SvdTest::testFloat() { - Matrix5x8f u; - Vector5f w; - Matrix5f v; - std::tie(u, w, v) = Algorithms::svd(af); + Matrix5x8 u{NoInit}; + Vector5 w{NoInit}; + Matrix5 v{NoInit}; + std::tie(u, w, v) = Algorithms::svd(a); - /* Test composition (single precision is not enough, test for similarity) */ - Matrix8f u2(u[0], u[1], u[2], u[3], u[4], Vector8f(), Vector8f(), Vector8f()); - Matrix5x8f w2 = Matrix5x8f::fromDiagonal(w); - CORRADE_VERIFY(Math::abs((u2*w2*v.transposed()-af).toVector()).max() < 1.0e-5f); + /* Test composition */ + Matrix8 u2{u[0], u[1], u[2], u[3], u[4], Vector8{}, Vector8{}, Vector8{}}; + Matrix5x8 w2 = Matrix5x8::fromDiagonal(w); + CORRADE_COMPARE(u2*w2*v.transposed(), a); /* Test that V is unitary */ - CORRADE_COMPARE(v*v.transposed(), Matrix5f{IdentityInit}); - CORRADE_COMPARE(v.transposed()*v, Matrix5f{IdentityInit}); + CORRADE_COMPARE(v*v.transposed(), Matrix5{IdentityInit}); + CORRADE_COMPARE(v.transposed()*v, Matrix5{IdentityInit}); - /* Test W (single precision is not enough, test for similarity) */ - CORRADE_VERIFY(Math::abs(w-expectedf).max() < 1.0e-5f); + /* Test W */ + CORRADE_COMPARE(w, expected); } }}}} diff --git a/src/Magnum/Math/Angle.h b/src/Magnum/Math/Angle.h index c5d40cdf4..2f8447234 100644 --- a/src/Magnum/Math/Angle.h +++ b/src/Magnum/Math/Angle.h @@ -127,20 +127,20 @@ template class Deg: public Unit { public: /** @brief Construct zero angle */ /* MSVC 2015 can't handle {} here */ - constexpr /*implicit*/ Deg(ZeroInitT = ZeroInit): Unit(ZeroInit) {} + constexpr /*implicit*/ Deg(ZeroInitT = ZeroInit) noexcept: Unit(ZeroInit) {} /** @brief Construct without initializing the contents */ /* MSVC 2015 can't handle {} here */ - explicit Deg(NoInitT): Unit(NoInit) {} + explicit Deg(NoInitT) noexcept: Unit(NoInit) {} /** @brief Explicit constructor from unitless type */ - constexpr explicit Deg(T value): Unit(value) {} - - /** @brief Copy constructor */ - constexpr /*implicit*/ Deg(Unit value): Unit(value) {} + constexpr explicit Deg(T value) noexcept: Unit(value) {} /** @brief Construct from another underlying type */ - template constexpr explicit Deg(Unit value): Unit(value) {} + template constexpr explicit Deg(Unit value) noexcept: Unit(value) {} + + /** @brief Copy constructor */ + constexpr /*implicit*/ Deg(Unit other) noexcept: Unit(other) {} /** * @brief Construct degrees from radians @@ -155,7 +155,6 @@ template class Deg: public Unit { namespace Literals { -#ifndef MAGNUM_TARGET_GLES /** @relatesalso Magnum::Math::Deg @brief Double-precision degree value literal @@ -165,10 +164,8 @@ Double cosine = Math::cos(60.0_deg); // cosine = 0.5 Double cosine = Math::cos(1.047_rad); // cosine = 0.5 @endcode @see @link operator""_degf() @endlink, @link operator""_rad() @endlink -@requires_gl Only single-precision types are available in OpenGL ES and WebGL. */ constexpr Deg operator "" _deg(long double value) { return Deg(Double(value)); } -#endif /** @relatesalso Magnum::Math::Deg @brief Single-precision degree value literal @@ -194,20 +191,20 @@ template class Rad: public Unit { public: /** @brief Default constructor */ /* MSVC 2015 can't handle {} here */ - constexpr /*implicit*/ Rad(ZeroInitT = ZeroInit): Unit(ZeroInit) {} + constexpr /*implicit*/ Rad(ZeroInitT = ZeroInit) noexcept: Unit(ZeroInit) {} /** @brief Construct without initializing the contents */ /* MSVC 2015 can't handle {} here */ - explicit Rad(NoInitT): Unit(NoInit) {} + explicit Rad(NoInitT) noexcept: Unit(NoInit) {} /** @brief Construct from unitless type */ - constexpr explicit Rad(T value): Unit(value) {} - - /** @brief Copy constructor */ - constexpr /*implicit*/ Rad(Unit value): Unit(value) {} + constexpr explicit Rad(T value) noexcept: Unit(value) {} /** @brief Construct from another underlying type */ - template constexpr explicit Rad(Unit value): Unit(value) {} + template constexpr explicit Rad(Unit value) noexcept: Unit(value) {} + + /** @brief Copy constructor */ + constexpr /*implicit*/ Rad(Unit value) noexcept: Unit(value) {} /** * @brief Construct radians from degrees @@ -222,16 +219,13 @@ template class Rad: public Unit { namespace Literals { -#ifndef MAGNUM_TARGET_GLES /** @relatesalso Magnum::Math::Rad @brief Double-precision radian value literal See @link operator""_deg() @endlink for more information. @see @link operator""_radf() @endlink -@requires_gl Only single-precision types are available in OpenGL ES and WebGL. */ constexpr Rad operator "" _rad(long double value) { return Rad(Double(value)); } -#endif /** @relatesalso Magnum::Math::Rad @brief Single-precision radian value literal @@ -260,11 +254,43 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& d #ifndef DOXYGEN_GENERATING_OUTPUT extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); #endif -#endif + +}} + +namespace Corrade { namespace Utility { + +/** @configurationvalue{Magnum::Math::Deg} */ +template struct ConfigurationValue> { + ConfigurationValue() = delete; + + /** @brief Writes degrees as a number */ + static std::string toString(const Magnum::Math::Deg& value, ConfigurationValueFlags flags) { + return ConfigurationValue::toString(T(value), flags); + } + + /** @brief Reads degrees as a number */ + static Magnum::Math::Deg fromString(const std::string& stringValue, ConfigurationValueFlags flags) { + return Magnum::Math::Deg(ConfigurationValue::fromString(stringValue, flags)); + } +}; + +/** @configurationvalue{Magnum::Math::Rad} */ +template struct ConfigurationValue> { + ConfigurationValue() = delete; + + /** @brief Writes degrees as a number */ + static std::string toString(const Magnum::Math::Rad& value, ConfigurationValueFlags flags) { + return ConfigurationValue::toString(T(value), flags); + } + + /** @brief Reads degrees as a number */ + static Magnum::Math::Rad fromString(const std::string& stringValue, ConfigurationValueFlags flags) { + return Magnum::Math::Rad(ConfigurationValue::fromString(stringValue, flags)); + } +}; }} diff --git a/src/Magnum/Math/Bezier.h b/src/Magnum/Math/Bezier.h new file mode 100644 index 000000000..f4c729514 --- /dev/null +++ b/src/Magnum/Math/Bezier.h @@ -0,0 +1,322 @@ +#ifndef Magnum_Math_Bezier_h +#define Magnum_Math_Bezier_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Ashwin Ravichandran + + 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::Math::Bezier, alias @ref Magnum::Math::QuadraticBezier, @ref Magnum::Math::QuadraticBezier2D, @ref Magnum::Math::QuadraticBezier3D, @ref Magnum::Math::CubicBezier, @ref Magnum::Math::CubicBezier2D, @ref Magnum::Math::CubicBezier3D + */ + +#include + +#include "Magnum/Math/Vector.h" + +namespace Magnum { namespace Math { + +/** +@brief Bézier curve +@tparam order Order of Bézier curve +@tparam dimensions Dimensions of control points +@tparam T Underlying data type + +Implementation of M-order N-dimensional +[Bézier Curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve). +@see @ref QuadraticBezier, @ref CubicBezier, @ref QuadraticBezier2D, + @ref QuadraticBezier3D, @ref CubicBezier2D, @ref CubicBezier3D +*/ +template class Bezier { + static_assert(order != 0, "Bezier cannot have zero order"); + + template friend class Bezier; + + public: + typedef T Type; /**< @brief Underlying data type */ + + enum: UnsignedInt { + Order = order, /**< Order of Bézier curve */ + Dimensions = dimensions /**< Dimensions of control points */ + }; + + /** + * @brief Default constructor + * + * Construct the curve with all control points being zero vectors. + */ + constexpr /*implicit*/ Bezier(ZeroInitT = ZeroInit) noexcept + /** @todoc remove workaround when doxygen is sane */ + #ifndef DOXYGEN_GENERATING_OUTPUT + /* MSVC 2015 can't handle {} here */ + : Bezier(typename Implementation::GenerateSequence::Type{}, ZeroInit) + #endif + {} + + /** @brief Construct Bézier without initializing the contents */ + explicit Bezier(NoInitT) noexcept + /** @todoc remove workaround when doxygen is sane */ + #ifndef DOXYGEN_GENERATING_OUTPUT + /* MSVC 2015 can't handle {} here */ + : Bezier(typename Implementation::GenerateSequence::Type{}, NoInit) + #endif + {} + + /** @brief Construct Bézier curve with given array of control points */ + template constexpr Bezier(const Vector& first, U... next) noexcept: _data{first, next...} { + static_assert(sizeof...(U) + 1 == order + 1, "Wrong number of arguments"); + } + + /** + * @brief Construct Bézier curve from another of different type + * + * Performs only default casting on the values, no rounding or + * anything else. + */ + template constexpr explicit Bezier(const Bezier& other) noexcept: Bezier{typename Implementation::GenerateSequence::Type(), other} {} + + /** @brief Equality comparison */ + bool operator==(const Bezier& other) const { + for(std::size_t i = 0; i != order + 1; ++i) + if((*this)[i] != other[i]) return false; + return true; + } + + /** @brief Non-equality comparison */ + bool operator!=(const Bezier& other) const { + return !operator==(other); + } + + /** + * @brief Control point access + * + * @p i should not be larger than @ref Order. + */ + Vector& operator[](std::size_t i) { return _data[i]; } + constexpr Vector operator[](std::size_t i) const { return _data[i]; } /**< @overload */ + + /** + * @brief Interpolate the curve at given position + * + * Returns point on the curve for given interpolation factor. Uses + * the [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm). + * @see @ref subdivide() + */ + Vector value(Float t) const { + return calculateIntermediatePoints(t)[0][order]; + } + + /** + * @brief Subdivide the curve at given position + * + * Returns two Bézier curves following the original curve, split at + * given interpolation factor. Uses the [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm). + * @see @ref value() + */ + std::pair, Bezier> subdivide(Float t) const { + const auto iPoints = calculateIntermediatePoints(t); + Bezier left, right; + for(std::size_t i = 0; i <= order; ++i) + left[i] = iPoints[0][i]; + for(std::size_t i = 0, j = order; i <= order; --j, ++i) + right[i] = iPoints[i][j]; + return {left, right}; + } + + private: + /* Implementation for Bezier::Bezier(const Bezier&) */ + template constexpr explicit Bezier(Implementation::Sequence, const Bezier& other) noexcept: _data{Vector(other._data[sequence])...} {} + + /* Implementation for Bezier::Bezier(ZeroInitT) and Bezier::Bezier(NoInitT) */ + /* MSVC 2015 can't handle {} here */ + template constexpr explicit Bezier(Implementation::Sequence, U): _data{Vector((static_cast(sequence), U{typename U::Init{}}))...} {} + + /* Calculates and returns all intermediate points generated when using De Casteljau's algorithm */ + std::array, order + 1> calculateIntermediatePoints(Float t) const { + std::array, order + 1> iPoints; + for(std::size_t i = 0; i <= order; ++i) { + iPoints[i][0] = _data[i]; + } + for(std::size_t r = 1; r <= order; ++r) { + for(std::size_t i = 0; i <= order - r; ++i) { + iPoints[i][r] = (1 - t)*iPoints[i][r - 1] + t*iPoints[i + 1][r - 1]; + } + } + return iPoints; + } + + Vector _data[order + 1]; +}; + +/** +@brief Quadratic Bézier curve + +Convenience alternative to `Bezier<2, dimensions, T>`. See @ref Bezier for more +information. +@see @ref QuadraticBezier2D, @ref QuadraticBezier3D +*/ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using QuadraticBezier = Bezier<2, dimensions, T>; +#endif + +/** +@brief Two-dimensional quadratic Bézier curve + +Convenience alternative to `QuadraticBezier<2, T>`. See @ref QuadraticBezier +and @ref Bezier for more information. +@see @ref QuadraticBezier3D, @ref Magnum::QuadraticBezier2D, + @ref Magnum::QuadraticBezier2Dd +*/ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using QuadraticBezier2D = QuadraticBezier<2, T>; +#endif + +/** +@brief Three-dimensional quadratic Bézier curve + +Convenience alternative to `QuadraticBezier<3, T>`. See @ref QuadraticBezier +and @ref Bezier for more information. +@see @ref QuadraticBezier2D, @ref Magnum::QuadraticBezier3D, + @ref Magnum::QuadraticBezier3Dd +*/ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using QuadraticBezier3D = QuadraticBezier<3, T>; +#endif + +/** +@brief Cubic Bézier curve + +Convenience alternative to `Bezier<3, dimensions, T>`. See @ref Bezier for more +information. +@see @ref CubicBezier2D, @ref CubicBezier3D +*/ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using CubicBezier = Bezier<3, dimensions, T>; +#endif + +/** +@brief Two-dimensional cubic Bézier curve + +Convenience alternative to `CubicBezier<2, T>`. See @ref CubicBezier +and @ref Bezier for more information. +@see @ref CubicBezier3D, @ref Magnum::CubicBezier2D, + @ref Magnum::CubicBezier2Dd +*/ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using CubicBezier2D = CubicBezier<2, T>; +#endif + +/** +@brief Three-dimensional cubic Bézier curve + +Convenience alternative to `CubicBezier<3, T>`. See @ref CubicBezier +and @ref Bezier for more information. +@see @ref CubicBezier2D, @ref Magnum::CubicBezier3D, + @ref Magnum::CubicBezier3Dd +*/ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using CubicBezier3D = CubicBezier<3, T>; +#endif + +/** @debugoperator{Magnum::Math::Bezier} */ +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, const Bezier& value) { + debug << "Bezier(" << Corrade::Utility::Debug::nospace; + for(UnsignedInt o = 0; o != order + 1; ++o) { + debug << (o ? ", {" : "{") << Corrade::Utility::Debug::nospace << value[o][0] << Corrade::Utility::Debug::nospace; + for(UnsignedInt i = 1; i != dimensions; ++i) + debug << "," << value[o][i] << Corrade::Utility::Debug::nospace; + debug << "}" << Corrade::Utility::Debug::nospace; + } + return debug << ")"; +} + +/* Explicit instantiation for types used in OpenGL */ +#ifndef DOXYGEN_GENERATING_OUTPUT +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 2, Float>&); +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 3, Float>&); +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 2, Float>&); +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 3, Float>&); +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 2, Double>&); +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 3, Double>&); +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 2, Double>&); +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 3, Double>&); +#endif + +}} + +namespace Corrade { namespace Utility { + +/** @configurationvalue{Magnum::Math::Bezier} */ +template struct ConfigurationValue> { + ConfigurationValue() = delete; + + /** @brief Writes elements separated with spaces */ + static std::string toString(const Magnum::Math::Bezier& value, ConfigurationValueFlags flags) { + std::string output; + + for(std::size_t o = 0; o != order + 1; ++o) { + for(std::size_t i = 0; i != dimensions; ++i) { + if(!output.empty()) output += ' '; + output += ConfigurationValue::toString(value[o][i], flags); + } + } + + return output; + } + + /** @brief Reads elements separated with whitespace */ + static Magnum::Math::Bezier fromString(const std::string& stringValue, ConfigurationValueFlags flags) { + Magnum::Math::Bezier result; + + std::size_t oldpos = 0, pos = std::string::npos, i = 0; + do { + pos = stringValue.find(' ', oldpos); + std::string part = stringValue.substr(oldpos, pos-oldpos); + + if(!part.empty()) { + result[i/dimensions][i%dimensions] = ConfigurationValue::fromString(part, flags); + ++i; + } + + oldpos = pos+1; + } while(pos != std::string::npos); + + return result; + } +}; + +#if !defined(DOXYGEN_GENERATING_OUTPUT) && !defined(__MINGW32__) +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +#endif + +}} + +#endif + diff --git a/src/Magnum/Math/BoolVector.h b/src/Magnum/Math/BoolVector.h index 40cf5e3f4..578e625a0 100644 --- a/src/Magnum/Math/BoolVector.h +++ b/src/Magnum/Math/BoolVector.h @@ -49,6 +49,13 @@ namespace Implementation { template struct GenerateSequence<0, sequence...> { typedef Sequence Type; }; + + template struct GenerateReverseSequence: + GenerateReverseSequence {}; + + template struct GenerateReverseSequence<0, sequence...> { + typedef Sequence Type; + }; #endif template constexpr T repeat(T value, std::size_t) { return value; } @@ -73,10 +80,10 @@ template class BoolVector { }; /** @brief Construct zero-filled boolean vector */ - constexpr /*implicit*/ BoolVector(ZeroInitT = ZeroInit): _data{} {} + constexpr /*implicit*/ BoolVector(ZeroInitT = ZeroInit) noexcept: _data{} {} /** @brief Construct without initializing the contents */ - explicit BoolVector(NoInitT) {} + explicit BoolVector(NoInitT) noexcept {} /** * @brief Construct boolean vector from segment values @@ -84,23 +91,20 @@ template class BoolVector { * @param next Values for next Bbit segments */ #ifdef DOXYGEN_GENERATING_OUTPUT - template constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next); + template constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next) noexcept; #else - template::type> constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next): _data{first, UnsignedByte(next)...} {} + template::type> constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next) noexcept: _data{first, UnsignedByte(next)...} {} #endif /** @brief Construct boolean vector with one value for all fields */ #ifdef DOXYGEN_GENERATING_OUTPUT - inline explicit BoolVector(T value); + explicit BoolVector(T value) noexcept; #else - template::value && size != 1, bool>::type> constexpr explicit BoolVector(T value): BoolVector(typename Implementation::GenerateSequence::Type(), value ? FullSegmentMask : 0) {} + template::value && size != 1, bool>::type> constexpr explicit BoolVector(T value) noexcept: BoolVector(typename Implementation::GenerateSequence::Type(), value ? FullSegmentMask : 0) {} #endif /** @brief Copy constructor */ - constexpr BoolVector(const BoolVector&) = default; - - /** @brief Copy assignment */ - BoolVector& operator=(const BoolVector&) = default; + constexpr /*implicit*/ BoolVector(const BoolVector&) noexcept = default; /** * @brief Raw data @@ -130,13 +134,33 @@ template class BoolVector { return !operator==(other); } - /** @brief Whether all bits are set */ + /** + * @brief Boolean conversion + * + * Equivalent to @ref all(). + * @see @ref any(), @ref none() + */ + explicit operator bool() const { return all(); } + + /** + * @brief Whether all bits are set + * + * @see @ref none(), @ref any(), @ref operator bool() + */ bool all() const; - /** @brief Whether no bits are set */ + /** + * @brief Whether no bits are set + * + * @see @ref all(), @ref any(), @ref operator bool() + */ bool none() const; - /** @brief Whether any bit is set */ + /** + * @brief Whether any bit is set + * + * @see @ref all(), @ref none(), @ref operator bool() + */ bool any() const { return !none(); } /** @brief Bitwise inversion */ diff --git a/src/Magnum/Math/CMakeLists.txt b/src/Magnum/Math/CMakeLists.txt index a39dca0ab..d6783821f 100644 --- a/src/Magnum/Math/CMakeLists.txt +++ b/src/Magnum/Math/CMakeLists.txt @@ -25,6 +25,7 @@ set(MagnumMath_HEADERS Angle.h + Bezier.h BoolVector.h Color.h Complex.h diff --git a/src/Magnum/Math/Color.h b/src/Magnum/Math/Color.h index 137ccc121..6269587d0 100644 --- a/src/Magnum/Math/Color.h +++ b/src/Magnum/Math/Color.h @@ -62,7 +62,7 @@ template typename std::enable_if::value, Colo case 3: return {p, q, value}; case 4: return {t, p, value}; case 5: return {value, p, q}; - default: CORRADE_ASSERT_UNREACHABLE(); + default: CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } } template inline typename std::enable_if::value, Color3>::type fromHSV(typename Color3::HSV hsv) { @@ -254,7 +254,7 @@ template class Color3: public Vector3 { * * All components are set to zero. */ - constexpr /*implicit*/ Color3(ZeroInitT = ZeroInit) + constexpr /*implicit*/ Color3(ZeroInitT = ZeroInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -263,7 +263,7 @@ template class Color3: public Vector3 { {} /** @copydoc Vector::Vector(NoInitT) */ - explicit Color3(NoInitT) + explicit Color3(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -275,7 +275,7 @@ template class Color3: public Vector3 { * @brief Gray constructor * @param rgb RGB value */ - constexpr explicit Color3(T rgb): Vector3(rgb) {} + constexpr explicit Color3(T rgb) noexcept: Vector3(rgb) {} /** * @brief Constructor @@ -283,7 +283,7 @@ template class Color3: public Vector3 { * @param g G value * @param b B value */ - constexpr /*implicit*/ Color3(T r, T g, T b): Vector3(r, g, b) {} + constexpr /*implicit*/ Color3(T r, T g, T b) noexcept: Vector3(r, g, b) {} /** * @copydoc Vector::Vector(const Vector&) @@ -292,10 +292,20 @@ template class Color3: public Vector3 { * @ref normalize() and @ref denormalize() instead. * See class documentation for more information. */ - template constexpr explicit Color3(const Vector<3, U>& other): Vector3(other) {} + template constexpr explicit Color3(const Vector<3, U>& other) noexcept: Vector3(other) {} + + /** @brief Construct color from external representation */ + template::from(std::declval())) + #else + decltype(Implementation::VectorConverter<3, T, U>()) + #endif + > + constexpr explicit Color3(const U& other): Vector3(Implementation::VectorConverter<3, T, U>::from(other)) {} /** @brief Copy constructor */ - constexpr Color3(const Vector<3, T>& other): Vector3(other) {} + constexpr /*implicit*/ Color3(const Vector<3, T>& other) noexcept: Vector3(other) {} /** * @brief Convert to HSV @@ -449,10 +459,10 @@ class Color4: public Vector4 { * * All components are set to zero. */ - constexpr /*implicit*/ Color4(): Vector4(T(0), T(0), T(0), T(0)) {} + constexpr /*implicit*/ Color4() noexcept: Vector4(T(0), T(0), T(0), T(0)) {} /** @copydoc Vector::Vector(ZeroInitT) */ - constexpr explicit Color4(ZeroInitT) + constexpr explicit Color4(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -461,7 +471,7 @@ class Color4: public Vector4 { {} /** @copydoc Vector::Vector(NoInitT) */ - explicit Color4(NoInitT) + explicit Color4(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -474,7 +484,7 @@ class Color4: public Vector4 { * @param alpha Alpha value, defaults to `1.0` for floating-point types * and maximum positive value for integral types. */ - constexpr explicit Color4(T rgb, T alpha = Implementation::fullChannel()): Vector4(rgb, rgb, rgb, alpha) {} + constexpr explicit Color4(T rgb, T alpha = Implementation::fullChannel()) noexcept: Vector4(rgb, rgb, rgb, alpha) {} /** * @brief Constructor @@ -484,7 +494,7 @@ class Color4: public Vector4 { * @param a A value, defaults to `1.0` for floating-point types and * maximum positive value for integral types. */ - constexpr /*implicit*/ Color4(T r, T g, T b, T a = Implementation::fullChannel()): Vector4(r, g, b, a) {} + constexpr /*implicit*/ Color4(T r, T g, T b, T a = Implementation::fullChannel()) noexcept: Vector4(r, g, b, a) {} /** * @brief Constructor @@ -493,7 +503,7 @@ class Color4: public Vector4 { */ /* Not marked as explicit, because conversion from Color3 to Color4 is fairly common, nearly always with A set to 1 */ - constexpr /*implicit*/ Color4(const Vector3& rgb, T a = Implementation::fullChannel()): Vector4(rgb[0], rgb[1], rgb[2], a) {} + constexpr /*implicit*/ Color4(const Vector3& rgb, T a = Implementation::fullChannel()) noexcept: Vector4(rgb[0], rgb[1], rgb[2], a) {} /** * @copydoc Vector::Vector(const Vector&) @@ -502,10 +512,20 @@ class Color4: public Vector4 { * @ref normalize() and @ref denormalize() instead. * See @ref Color3 class documentation for more information. */ - template constexpr explicit Color4(const Vector<4, U>& other): Vector4(other) {} + template constexpr explicit Color4(const Vector<4, U>& other) noexcept: Vector4(other) {} + + /** @brief Construct color from external representation */ + template::from(std::declval())) + #else + decltype(Implementation::VectorConverter<4, T, U>()) + #endif + > + constexpr explicit Color4(const U& other): Vector4(Implementation::VectorConverter<4, T, U>::from(other)) {} /** @brief Copy constructor */ - constexpr Color4(const Vector<4, T>& other): Vector4(other) {} + constexpr /*implicit*/ Color4(const Vector<4, T>& other) noexcept: Vector4(other) {} /** @copydoc Color3::toHSV() */ constexpr HSV toHSV() const { diff --git a/src/Magnum/Math/Complex.h b/src/Magnum/Math/Complex.h index 9f2d0a614..4c6a89c42 100644 --- a/src/Magnum/Math/Complex.h +++ b/src/Magnum/Math/Complex.h @@ -142,13 +142,13 @@ template class Complex { * c = 1 + i0 * @f] */ - constexpr /*implicit*/ Complex(IdentityInitT = IdentityInit): _real(T(1)), _imaginary(T(0)) {} + constexpr /*implicit*/ Complex(IdentityInitT = IdentityInit) noexcept: _real(T(1)), _imaginary(T(0)) {} /** @brief Construct zero-initialized complex number */ - constexpr explicit Complex(ZeroInitT): _real{}, _imaginary{} {} + constexpr explicit Complex(ZeroInitT) noexcept: _real{}, _imaginary{} {} /** @brief Construct without initializing the contents */ - explicit Complex(NoInitT) {} + explicit Complex(NoInitT) noexcept {} /** * @brief Construct complex number from real and imaginary part @@ -157,7 +157,7 @@ template class Complex { * c = a + ib * @f] */ - constexpr /*implicit*/ Complex(T real, T imaginary): _real(real), _imaginary(imaginary) {} + constexpr /*implicit*/ Complex(T real, T imaginary) noexcept: _real(real), _imaginary(imaginary) {} /** * @brief Construct complex number from vector @@ -167,7 +167,7 @@ template class Complex { * @f] * @see @ref operator Vector2(), @ref transformVector() */ - constexpr explicit Complex(const Vector2& vector): _real(vector.x()), _imaginary(vector.y()) {} + constexpr explicit Complex(const Vector2& vector) noexcept: _real(vector.x()), _imaginary(vector.y()) {} /** * @brief Construct complex number from another of different type @@ -175,11 +175,14 @@ template class Complex { * Performs only default casting on the values, no rounding or anything * else. */ - template constexpr explicit Complex(const Complex& other): _real{T(other._real)}, _imaginary{T(other._imaginary)} {} + template constexpr explicit Complex(const Complex& other) noexcept: _real{T(other._real)}, _imaginary{T(other._imaginary)} {} /** @brief Construct complex number from external representation */ template::from(std::declval()))> constexpr explicit Complex(const U& other): Complex{Implementation::ComplexConverter::from(other)} {} + /** @brief Copy constructor */ + constexpr /*implicit*/ Complex(const Complex&) noexcept = default; + /** @brief Convert complex number to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { return Implementation::ComplexConverter::to(*this); @@ -490,10 +493,8 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& d /* Explicit instantiation for commonly used types */ #ifndef DOXYGEN_GENERATING_OUTPUT extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Complex&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Complex&); #endif -#endif }} diff --git a/src/Magnum/Math/Constants.h b/src/Magnum/Math/Constants.h index dedc89e3d..cfa2f999d 100644 --- a/src/Magnum/Math/Constants.h +++ b/src/Magnum/Math/Constants.h @@ -30,11 +30,7 @@ */ #include - -#include "Magnum/configure.h" -#ifndef MAGNUM_TARGET_GLES #include -#endif #include "Magnum/Types.h" @@ -83,7 +79,6 @@ template struct Constants { }; #ifndef DOXYGEN_GENERATING_OUTPUT -#ifndef MAGNUM_TARGET_GLES template<> struct Constants { Constants() = delete; @@ -97,7 +92,6 @@ template<> struct Constants { static constexpr Double nan() { return std::numeric_limits::quiet_NaN(); } static constexpr Double inf() { return std::numeric_limits::infinity(); } }; -#endif template<> struct Constants { Constants() = delete; diff --git a/src/Magnum/Math/Dual.h b/src/Magnum/Math/Dual.h index 5080c9b2d..14aa88488 100644 --- a/src/Magnum/Math/Dual.h +++ b/src/Magnum/Math/Dual.h @@ -57,15 +57,24 @@ template class Dual { * * Both parts are default-constructed. */ - constexpr /*implicit*/ Dual(): _real(), _dual() {} + constexpr /*implicit*/ Dual() noexcept: _real{}, _dual{} {} + + /** @brief Construct zero-initialized dual number */ + #ifdef DOXYGEN_GENERATING_OUTPUT + constexpr /*implicit*/ Dual(ZeroInitT) noexcept; + #else + /* MSVC 2015 can't handle {} instead of ::value */ + template::value>::type> constexpr /*implicit*/ Dual(ZeroInitT) noexcept: _real{}, _dual{} {} + template::value>::type> constexpr /*implicit*/ Dual(ZeroInitT) noexcept: _real{ZeroInit}, _dual{ZeroInit} {} + #endif /** @brief Construct without initializing the contents */ #ifdef DOXYGEN_GENERATING_OUTPUT - explicit Dual(NoInitT); + explicit Dual(NoInitT) noexcept; #else /* MSVC 2015 can't handle {} instead of ::value */ - template::value>::type> Dual(NoInitT) {} - template::value>::type> Dual(NoInitT): _real{NoInit}, _dual{NoInit} {} + template::value>::type> explicit Dual(NoInitT) noexcept {} + template::value>::type> explicit Dual(NoInitT) noexcept: _real{NoInit}, _dual{NoInit} {} #endif /** @@ -75,7 +84,7 @@ template class Dual { * \hat a = a_0 + \epsilon a_\epsilon * @f] */ - constexpr /*implicit*/ Dual(const T& real, const T& dual = T()): _real(real), _dual(dual) {} + constexpr /*implicit*/ Dual(const T& real, const T& dual = T()) noexcept: _real(real), _dual(dual) {} /** * @brief Construct dual number from another of different type @@ -88,7 +97,10 @@ template class Dual { * // integral == {1, 2} * @endcode */ - template constexpr explicit Dual(const Dual& other): _real{T(other._real)}, _dual{T(other._dual)} {} + template constexpr explicit Dual(const Dual& other) noexcept: _real{T(other._real)}, _dual{T(other._dual)} {} + + /** @brief Copy constructor */ + constexpr /*implicit*/ Dual(const Dual&) noexcept = default; /** @brief Equality comparison */ bool operator==(const Dual& other) const { diff --git a/src/Magnum/Math/DualComplex.h b/src/Magnum/Math/DualComplex.h index e3c445839..ad13a5095 100644 --- a/src/Magnum/Math/DualComplex.h +++ b/src/Magnum/Math/DualComplex.h @@ -104,13 +104,13 @@ template class DualComplex: public Dual> { * @f] */ #ifdef DOXYGEN_GENERATING_OUTPUT - constexpr /*implicit*/ DualComplex(IdentityInitT = IdentityInit); + constexpr /*implicit*/ DualComplex(IdentityInitT = IdentityInit) noexcept; #else - constexpr /*implicit*/ DualComplex(IdentityInitT = IdentityInit): Dual>({}, {T(0), T(0)}) {} + constexpr /*implicit*/ DualComplex(IdentityInitT = IdentityInit) noexcept: Dual>({}, {T(0), T(0)}) {} #endif /** @brief Construct zero-initialized dual complex number */ - constexpr explicit DualComplex(ZeroInitT) + constexpr explicit DualComplex(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -119,7 +119,7 @@ template class DualComplex: public Dual> { {} /** @brief Construct without initializing the contents */ - explicit DualComplex(NoInitT) + explicit DualComplex(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -134,7 +134,10 @@ template class DualComplex: public Dual> { * \hat c = c_0 + \epsilon c_\epsilon * @f] */ - constexpr /*implicit*/ DualComplex(const Complex& real, const Complex& dual = Complex(T(0), T(0))): Dual>(real, dual) {} + constexpr /*implicit*/ DualComplex(const Complex& real, const Complex& dual = Complex(T(0), T(0))) noexcept: Dual>(real, dual) {} + + /* No constructor from a pair of Dual values because that would be + ambiguous with the above */ /** * @brief Construct dual complex number from vector @@ -144,9 +147,9 @@ template class DualComplex: public Dual> { * @f] */ #ifdef DOXYGEN_GENERATING_OUTPUT - constexpr explicit DualComplex(const Vector2& vector); + constexpr explicit DualComplex(const Vector2& vector) noexcept; #else - constexpr explicit DualComplex(const Vector2& vector): Dual>({}, Complex(vector)) {} + constexpr explicit DualComplex(const Vector2& vector) noexcept: Dual>({}, Complex(vector)) {} #endif /** @@ -155,7 +158,7 @@ template class DualComplex: public Dual> { * Performs only default casting on the values, no rounding or anything * else. */ - template constexpr explicit DualComplex(const DualComplex& other) + template constexpr explicit DualComplex(const DualComplex& other) noexcept #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ : Dual>(other) @@ -166,7 +169,7 @@ template class DualComplex: public Dual> { template::from(std::declval()))> constexpr explicit DualComplex(const U& other): DualComplex{Implementation::DualComplexConverter::from(other)} {} /** @brief Copy constructor */ - constexpr DualComplex(const Dual>& other): Dual>(other) {} + constexpr /*implicit*/ DualComplex(const Dual>& other) noexcept: Dual>(other) {} /** @brief Convert dual complex number to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { @@ -367,10 +370,8 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& d /* Explicit instantiation for commonly used types */ #ifndef DOXYGEN_GENERATING_OUTPUT extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualComplex&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualComplex&); #endif -#endif }} diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index 4500613ab..d938f8b0e 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -32,6 +32,7 @@ #include #include "Magnum/Math/Dual.h" +#include "Magnum/Math/Functions.h" #include "Magnum/Math/Matrix4.h" #include "Magnum/Math/Quaternion.h" @@ -163,7 +164,7 @@ template class DualQuaternion: public Dual> { * \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol 0, 0] * @f] */ - constexpr /*implicit*/ DualQuaternion(IdentityInitT = IdentityInit) + constexpr /*implicit*/ DualQuaternion(IdentityInitT = IdentityInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Dual>({}, {{}, T(0)}) @@ -171,7 +172,7 @@ template class DualQuaternion: public Dual> { {} /** @brief Construct zero-initialized dual quaternion */ - constexpr explicit DualQuaternion(ZeroInitT) + constexpr explicit DualQuaternion(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -180,7 +181,7 @@ template class DualQuaternion: public Dual> { {} /** @brief Construct without initializing the contents */ - explicit DualQuaternion(NoInitT) + explicit DualQuaternion(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -195,7 +196,7 @@ template class DualQuaternion: public Dual> { * \hat q = q_0 + \epsilon q_\epsilon * @f] */ - constexpr /*implicit*/ DualQuaternion(const Quaternion& real, const Quaternion& dual = Quaternion({}, T(0))): Dual>(real, dual) {} + constexpr /*implicit*/ DualQuaternion(const Quaternion& real, const Quaternion& dual = Quaternion({}, T(0))) noexcept: Dual>(real, dual) {} /** * @brief Construct dual quaternion from dual vector and scalar parts @@ -204,7 +205,7 @@ template class DualQuaternion: public Dual> { * \hat q = [\hat{\boldsymbol v}, \hat s] = [\boldsymbol v_0, s_0] + \epsilon [\boldsymbol v_\epsilon, s_\epsilon] * @f] */ - constexpr /*implicit*/ DualQuaternion(const Dual>& vector, const Dual& scalar) + constexpr /*implicit*/ DualQuaternion(const Dual>& vector, const Dual& scalar) noexcept #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ : Dual>({vector.real(), scalar.real()}, {vector.dual(), scalar.dual()}) @@ -220,9 +221,9 @@ template class DualQuaternion: public Dual> { * @see @ref transformPointNormalized() */ #ifdef DOXYGEN_GENERATING_OUTPUT - constexpr explicit DualQuaternion(const Vector3& vector); + constexpr explicit DualQuaternion(const Vector3& vector) noexcept; #else - constexpr explicit DualQuaternion(const Vector3& vector): Dual>({}, {vector, T(0)}) {} + constexpr explicit DualQuaternion(const Vector3& vector) noexcept: Dual>({}, {vector, T(0)}) {} #endif /** @@ -231,13 +232,13 @@ template class DualQuaternion: public Dual> { * Performs only default casting on the values, no rounding or anything * else. */ - template constexpr explicit DualQuaternion(const DualQuaternion& other): Dual>(other) {} + template constexpr explicit DualQuaternion(const DualQuaternion& other) noexcept: Dual>(other) {} /** @brief Construct dual quaternion from external representation */ template::from(std::declval()))> constexpr explicit DualQuaternion(const U& other): DualQuaternion{Implementation::DualQuaternionConverter::from(other)} {} /** @brief Copy constructor */ - constexpr DualQuaternion(const Dual>& other): Dual>(other) {} + constexpr /*implicit*/ DualQuaternion(const Dual>& other) noexcept: Dual>(other) {} /** @brief Convert dual quaternion to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { @@ -254,11 +255,11 @@ template class DualQuaternion: public Dual> { * @todoc Improve the equation as in Quaternion::isNormalized() */ bool isNormalized() const { - /* Comparing dual part classically, as comparing sqrt() of it would - lead to overly strict precision */ + /* Comparing dual part to zero considering the magnitude of the + translation -- the epsilon be much larger for large values. */ Dual a = lengthSquared(); return Implementation::isNormalizedSquared(a.real()) && - TypeTraits::equals(a.dual(), T(0)); + TypeTraits::equalsZero(a.dual(), Math::max(Math::abs(Math::Dual>::dual().vector()).max(), Math::abs(Math::Dual>::dual().scalar()))); } /** @@ -448,10 +449,8 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& d /* Explicit instantiation for commonly used types */ #ifndef DOXYGEN_GENERATING_OUTPUT extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualQuaternion&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualQuaternion&); #endif -#endif }} diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index 3c3ff7b57..333313892 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -498,7 +498,10 @@ template inline T fma(const T& a, const T& b, const T& c); #else template inline typename std::enable_if::value, T>::type fma(T a, T b, T c) { /** @todo Remove when newlib has this fixed */ - #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) + /* On Emscripten it works with -O2 but not with -O1 (function not defined). + I guess that's only because -O2 optimizes it out, so disabling it there + also */ + #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) && !defined(CORRADE_TARGET_EMSCRIPTEN) return std::fma(a, b, c); #else return a*b + c; diff --git a/src/Magnum/Math/Math.h b/src/Magnum/Math/Math.h index f9a3d19bf..23fc234ee 100644 --- a/src/Magnum/Math/Math.h +++ b/src/Magnum/Math/Math.h @@ -41,6 +41,14 @@ namespace Magnum { namespace Math { #ifndef DOXYGEN_GENERATING_OUTPUT /* Class Constants used only statically */ +template class Bezier; +template using QuadraticBezier = Bezier<2, dimensions, T>; +template using CubicBezier = Bezier<3, dimensions, T>; +template using QuadraticBezier2D = QuadraticBezier<2, T>; +template using QuadraticBezier3D = QuadraticBezier<3, T>; +template using CubicBezier2D = CubicBezier<2, T>; +template using CubicBezier3D = CubicBezier<3, T>; + template class Complex; template class Dual; template class DualComplex; diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 6be18b9fd..8d204b59f 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -83,7 +83,7 @@ template class Matrix: public RectangularMatrix class Matrix: public RectangularMatrix class Matrix: public RectangularMatrix class Matrix: public RectangularMatrix constexpr /*implicit*/ Matrix(const Vector& first, const U&... next): RectangularMatrix(first, next...) {} + template constexpr /*implicit*/ Matrix(const Vector& first, const U&... next) noexcept: RectangularMatrix(first, next...) {} /** * @brief Construct matrix from another of different type @@ -128,13 +128,13 @@ template class Matrix: public RectangularMatrix constexpr explicit Matrix(const RectangularMatrix& other): RectangularMatrix(other) {} + template constexpr explicit Matrix(const RectangularMatrix& other) noexcept: RectangularMatrix(other) {} /** @brief Construct matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} /** @brief Copy constructor */ - constexpr Matrix(const RectangularMatrix& other): RectangularMatrix(other) {} + constexpr /*implicit*/ Matrix(const RectangularMatrix& other) noexcept: RectangularMatrix(other) {} /** * @brief Whether the matrix is orthogonal @@ -163,7 +163,8 @@ template class Matrix: public RectangularMatrix class Matrix: public RectangularMatrix inverted() const; @@ -333,7 +335,7 @@ template bool Matrix::isOrthogonal() const { } template Matrix Matrix::ij(const std::size_t skipCol, const std::size_t skipRow) const { - Matrix out{ZeroInit}; + Matrix out{NoInit}; for(std::size_t col = 0; col != size-1; ++col) for(std::size_t row = 0; row != size-1; ++row) @@ -344,7 +346,7 @@ template Matrix Matrix::ij(const } template Matrix Matrix::inverted() const { - Matrix out{ZeroInit}; + Matrix out{NoInit}; const T _determinant = determinant(); diff --git a/src/Magnum/Math/Matrix3.h b/src/Magnum/Math/Matrix3.h index 0906b4be4..9eb69bf2d 100644 --- a/src/Magnum/Math/Matrix3.h +++ b/src/Magnum/Math/Matrix3.h @@ -49,6 +49,13 @@ template class Matrix3: public Matrix3x3 { * @brief 2D translation matrix * @param vector Translation vector * + * @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & 0 & v_x \\ + * 0 & 1 & v_y \\ + * 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref translation() const, @ref DualComplex::translation(), * @ref Matrix4::translation(const Vector3&), * @ref Vector2::xAxis(), @ref Vector2::yAxis() @@ -63,6 +70,13 @@ template class Matrix3: public Matrix3x3 { * @brief 2D scaling matrix * @param vector Scaling vector * + * @f[ + * \boldsymbol{A} = \begin{pmatrix} + * v_x & 0 & 0 \\ + * 0 & v_y & 0 \\ + * 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref rotationScaling(), * @ref Matrix4::scaling(const Vector3&), * @ref Vector2::xScale(), @ref Vector2::yScale() @@ -77,6 +91,13 @@ template class Matrix3: public Matrix3x3 { * @brief 2D rotation matrix * @param angle Rotation angle (counterclockwise) * + * @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \cos\theta & -\sin\theta & 0 \\ + * \sin\theta & \cos\theta & 0 \\ + * 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref rotation() const, @ref Complex::rotation(), * @ref DualComplex::rotation(), * @ref Matrix4::rotation(Rad, const Vector3&) @@ -90,7 +111,9 @@ template class Matrix3: public Matrix3x3 { * Expects that the normal is normalized. Reflection along axes can be * done in a slightly simpler way also using @ref scaling(), e.g. * `Matrix3::reflection(Vector2::yAxis())` is equivalent to - * `Matrix3::scaling(Vector2::yScale(-1.0f))`. + * `Matrix3::scaling(Vector2::yScale(-1.0f))`. @f[ + * \boldsymbol{A} = \boldsymbol{I} - 2 \boldsymbol{NN}^T ~~~~~ \boldsymbol{N} = \begin{pmatrix} n_x \\ n_y \end{pmatrix} + * @f] * @see @ref Matrix4::reflection(), @ref Vector::isNormalized() */ static Matrix3 reflection(const Vector2& normal) { @@ -103,7 +126,13 @@ template class Matrix3: public Matrix3x3 { * @brief 2D shearing matrix along X axis * @param amount Shearing amount * - * Y axis remains unchanged. + * Y axis remains unchanged. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & v_x & 0 \\ + * 0 & 1 & 0 \\ + * 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref shearingY(), @ref Matrix4::shearingXY(), * @ref Matrix4::shearingXZ(), @ref Matrix4::shearingYZ() */ @@ -117,7 +146,13 @@ template class Matrix3: public Matrix3x3 { * @brief 2D shearing matrix along Y axis * @param amount Shearing amount * - * X axis remains unchanged. + * X axis remains unchanged. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & 0 & 0 \\ + * v_y & 1 & 0 \\ + * 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref shearingX(), @ref Matrix4::shearingXY(), * @ref Matrix4::shearingXZ(), @ref Matrix4::shearingYZ() */ @@ -131,6 +166,13 @@ template class Matrix3: public Matrix3x3 { * @brief 2D projection matrix * @param size Size of the view * + * @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \frac{2}{s_x} & 0 & 0 \\ + * 0 & \frac{2}{s_y} & 0 \\ + * 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref Matrix4::orthographicProjection(), * @ref Matrix4::perspectiveProjection() */ @@ -159,7 +201,7 @@ template class Matrix3: public Matrix3x3 { * Creates identity matrix. @p value allows you to specify value on * diagonal. */ - constexpr /*implicit*/ Matrix3(IdentityInitT = IdentityInit, T value = T{1}) + constexpr /*implicit*/ Matrix3(IdentityInitT = IdentityInit, T value = T{1}) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -168,7 +210,7 @@ template class Matrix3: public Matrix3x3 { {} /** @copydoc Matrix::Matrix(ZeroInitT) */ - constexpr explicit Matrix3(ZeroInitT) + constexpr explicit Matrix3(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -177,7 +219,7 @@ template class Matrix3: public Matrix3x3 { {} /** @copydoc Matrix::Matrix(NoInitT) */ - constexpr explicit Matrix3(NoInitT) + constexpr explicit Matrix3(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -186,16 +228,16 @@ template class Matrix3: public Matrix3x3 { {} /** @brief Matrix from column vectors */ - constexpr /*implicit*/ Matrix3(const Vector3& first, const Vector3& second, const Vector3& third): Matrix3x3(first, second, third) {} + constexpr /*implicit*/ Matrix3(const Vector3& first, const Vector3& second, const Vector3& third) noexcept: Matrix3x3(first, second, third) {} /** @copydoc Matrix::Matrix(const RectangularMatrix&) */ - template constexpr explicit Matrix3(const RectangularMatrix<3, 3, U>& other): Matrix3x3(other) {} + template constexpr explicit Matrix3(const RectangularMatrix<3, 3, U>& other) noexcept: Matrix3x3(other) {} /** @brief Construct matrix from external representation */ - template::from(std::declval()))> constexpr explicit Matrix3(const U& other): Matrix3x3(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {} + template::from(std::declval()))> constexpr explicit Matrix3(const U& other) noexcept: Matrix3x3(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {} /** @brief Copy constructor */ - constexpr Matrix3(const RectangularMatrix<3, 3, T>& other): Matrix3x3(other) {} + constexpr /*implicit*/ Matrix3(const RectangularMatrix<3, 3, T>& other) noexcept: Matrix3x3(other) {} /** * @brief Check whether the matrix represents rigid transformation diff --git a/src/Magnum/Math/Matrix4.h b/src/Magnum/Math/Matrix4.h index 6e30f3156..fda1c3a6d 100644 --- a/src/Magnum/Math/Matrix4.h +++ b/src/Magnum/Math/Matrix4.h @@ -51,9 +51,17 @@ See @ref matrix-vector and @ref transformations for brief introduction. template class Matrix4: public Matrix4x4 { public: /** - * @brief 3D translation + * @brief 3D translation matrix * @param vector Translation vector * + * @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & 0 & 0 & v_x \\ + * 0 & 1 & 0 & v_y \\ + * 0 & 0 & 1 & v_z \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref translation(), @ref DualQuaternion::translation(), * @ref Matrix3::translation(const Vector2&), * @ref Vector3::xAxis(), @ref Vector3::yAxis(), @@ -67,9 +75,17 @@ template class Matrix4: public Matrix4x4 { } /** - * @brief 3D scaling + * @brief 3D scaling matrix * @param vector Scaling vector * + * @f[ + * \boldsymbol{A} = \begin{pmatrix} + * v_x & 0 & 0 & 0 \\ + * 0 & v_y & 0 & 0 \\ + * 0 & 0 & v_z & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref rotationScaling(), * @ref Matrix3::scaling(const Vector2&), * @ref Vector3::xScale(), @ref Vector3::yScale(), @@ -83,13 +99,20 @@ template class Matrix4: public Matrix4x4 { } /** - * @brief 3D rotation around arbitrary axis + * @brief 3D rotation matrix around arbitrary axis * @param angle Rotation angle (counterclockwise) * @param normalizedAxis Normalized rotation axis * * Expects that the rotation axis is normalized. If possible, use * faster alternatives like @ref rotationX(), @ref rotationY() and - * @ref rotationZ(). + * @ref rotationZ(). @f[ + * \boldsymbol{A} = \begin{pmatrix} + * v_{x}v_{x}(1 - \cos\theta) + \cos\theta & v_{y}v_{x}(1 - \cos\theta) - v_{z}\sin \theta & v_{z}v_{x}(1 - \cos\theta) + v_{y}\sin\theta & 0 \\ + * v_{x}v_{y}(1 - \cos\theta) + v_{z}\sin\theta & v_{y}v_{y}(1 - \cos\theta) + \cos\theta & v_{z}v_{y}(1 - \cos\theta) - v_{x}\sin\theta & 0 \\ + * v_{x}v_{z}(1 - \cos\theta) - v_{y}\sin\theta & v_{y}v_{z}(1 - \cos\theta)+v_{x}\sin\theta & v_{z}v_{z}(1 - \cos\theta) + \cos\theta & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref rotation() const, @ref Quaternion::rotation(), * @ref DualQuaternion::rotation(), @ref Matrix3::rotation(Rad), * @ref Vector3::xAxis(), @ref Vector3::yAxis(), @@ -98,10 +121,17 @@ template class Matrix4: public Matrix4x4 { static Matrix4 rotation(Rad angle, const Vector3& normalizedAxis); /** - * @brief 3D rotation around X axis + * @brief 3D rotation matrix around X axis * @param angle Rotation angle (counterclockwise) * - * Faster than calling `Matrix4::rotation(angle, Vector3::xAxis())`. + * Faster than calling `Matrix4::rotation(angle, Vector3::xAxis())`. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & 0 & 0 & 0 \\ + * 0 & \cos\theta & -\sin\theta & 0 \\ + * 0 & \sin\theta & \cos\theta & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref rotation(Rad, const Vector3&), @ref rotationY(), * @ref rotationZ(), @ref rotation() const, * @ref Quaternion::rotation(), @ref Matrix3::rotation(Rad) @@ -109,10 +139,17 @@ template class Matrix4: public Matrix4x4 { static Matrix4 rotationX(Rad angle); /** - * @brief 3D rotation around Y axis + * @brief 3D rotation matrix around Y axis * @param angle Rotation angle (counterclockwise) * - * Faster than calling `Matrix4::rotation(angle, Vector3::yAxis())`. + * Faster than calling `Matrix4::rotation(angle, Vector3::yAxis())`. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \cos\theta & 0 & \sin\theta & 0 \\ + * 0 & 1 & 0 & 0 \\ + * -\sin\theta & 0 & \cos\theta & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref rotation(Rad, const Vector3&), @ref rotationX(), * @ref rotationZ(), @ref rotation() const, * @ref Quaternion::rotation(), @ref Matrix3::rotation(Rad) @@ -123,7 +160,14 @@ template class Matrix4: public Matrix4x4 { * @brief 3D rotation matrix around Z axis * @param angle Rotation angle (counterclockwise) * - * Faster than calling `Matrix4::rotation(angle, Vector3::zAxis())`. + * Faster than calling `Matrix4::rotation(angle, Vector3::zAxis())`. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \cos\theta & -\sin\theta & 0 & 0 \\ + * \sin\theta & \cos\theta & 0 & 0 \\ + * 0 & 0 & 1 & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref rotation(Rad, const Vector3&), @ref rotationX(), * @ref rotationY(), @ref rotation() const, * @ref Quaternion::rotation(), @ref Matrix3::rotation(Rad) @@ -137,17 +181,26 @@ template class Matrix4: public Matrix4x4 { * Expects that the normal is normalized. Reflection along axes can be * done in a slightly simpler way also using @ref scaling(), e.g. * `Matrix4::reflection(Vector3::yAxis())` is equivalent to - * `Matrix4::scaling(Vector3::yScale(-1.0f))`. + * `Matrix4::scaling(Vector3::yScale(-1.0f))`. @f[ + * \boldsymbol{A} = \boldsymbol{I} - 2 \boldsymbol{NN}^T ~~~~~ \boldsymbol{N} = \begin{pmatrix} n_x \\ n_y \\ n_z \end{pmatrix} + * @f] * @see @ref Matrix3::reflection(), @ref Vector::isNormalized() */ static Matrix4 reflection(const Vector3& normal); /** - * @brief 3D shearing along XY plane + * @brief 3D shearing matrix along XY plane * @param amountX Amount of shearing along X axis * @param amountY Amount of shearing along Y axis * - * Z axis remains unchanged. + * Z axis remains unchanged. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & 0 & v_x & 0 \\ + * 0 & 1 & v_y & 0 \\ + * 0 & 0 & 1 & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref shearingXZ(), @ref shearingYZ(), @ref Matrix3::shearingX(), * @ref Matrix3::shearingY() */ @@ -159,11 +212,18 @@ template class Matrix4: public Matrix4x4 { } /** - * @brief 3D shearing along XZ plane + * @brief 3D shearing matrix along XZ plane * @param amountX Amount of shearing along X axis * @param amountZ Amount of shearing along Z axis * - * Y axis remains unchanged. + * Y axis remains unchanged. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & v_x & 0 & 0 \\ + * 0 & 1 & 0 & 0 \\ + * 0 & v_z & 1 & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref shearingXY(), @ref shearingYZ(), @ref Matrix3::shearingX(), * @ref Matrix3::shearingY() */ @@ -175,11 +235,18 @@ template class Matrix4: public Matrix4x4 { } /** - * @brief 3D shearing along YZ plane + * @brief 3D shearing matrix along YZ plane * @param amountY Amount of shearing along Y axis * @param amountZ Amount of shearing along Z axis * - * X axis remains unchanged. + * X axis remains unchanged. @f[ + * \boldsymbol{A} = \begin{pmatrix} + * 1 & 0 & 0 & 0 \\ + * v_y & 1 & 0 & 0 \\ + * v_z & 0 & 1 & 0 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref shearingXY(), @ref shearingXZ(), @ref Matrix3::shearingX(), * @ref Matrix3::shearingY() */ @@ -193,9 +260,17 @@ template class Matrix4: public Matrix4x4 { /** * @brief 3D orthographic projection matrix * @param size Size of the view - * @param near Near clipping plane - * @param far Far clipping plane + * @param near Distance to near clipping plane, positive is ahead + * @param far Distance to far clipping plane, positive is ahead * + * @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \frac{2}{s_x} & 0 & 0 & 0 \\ + * 0 & \frac{2}{s_y} & 0 & 0 \\ + * 0 & 0 & \frac{2}{n - f} & \frac{2n}{n - f} - 1 \\ + * 0 & 0 & 0 & 1 + * \end{pmatrix} + * @f] * @see @ref perspectiveProjection(), @ref Matrix3::projection() */ static Matrix4 orthographicProjection(const Vector2& size, T near, T far); @@ -203,10 +278,28 @@ template class Matrix4: public Matrix4x4 { /** * @brief 3D perspective projection matrix * @param size Size of near clipping plane - * @param near Near clipping plane - * @param far Far clipping plane + * @param near Distance to near clipping plane, positive is ahead + * @param far Distance to far clipping plane, positive is ahead + * + * If @p far is finite, the result is: @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \frac{2n}{s_x} & 0 & 0 & 0 \\ + * 0 & \frac{2n}{s_y} & 0 & 0 \\ + * 0 & 0 & \frac{n + f}{n - f} & \frac{2nf}{n - f} \\ + * 0 & 0 & -1 & 0 + * \end{pmatrix} + * @f] * - * @see @ref orthographicProjection(), @ref Matrix3::projection() + * For infinite @p far, the result is: @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \frac{2n}{s_x} & 0 & 0 & 0 \\ + * 0 & \frac{2n}{s_y} & 0 & 0 \\ + * 0 & 0 & -1 & -2n \\ + * 0 & 0 & -1 & 0 + * \end{pmatrix} + * @f] + * @see @ref orthographicProjection(), @ref Matrix3::projection(), + * @ref Constants::inf() */ static Matrix4 perspectiveProjection(const Vector2& size, T near, T far); @@ -217,7 +310,25 @@ template class Matrix4: public Matrix4x4 { * @param near Near clipping plane * @param far Far clipping plane * - * @see @ref orthographicProjection(), @ref Matrix3::projection() + * If @p far is finite, the result is: @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \frac{1}{\tan{\frac{\theta}{2}}} & 0 & 0 & 0 \\ + * 0 & \frac{a}{\tan{\frac{\theta}{2}}} & 0 & 0 \\ + * 0 & 0 & \frac{n + f}{n - f} & \frac{2nf}{n - f} \\ + * 0 & 0 & -1 & 0 + * \end{pmatrix} + * @f] + * + * For infinite @p far, the result is: @f[ + * \boldsymbol{A} = \begin{pmatrix} + * \frac{1}{\tan{\frac{\theta}{2}}} & 0 & 0 & 0 \\ + * 0 & \frac{a}{\tan{\frac{\theta}{2}}} & 0 & 0 \\ + * 0 & 0 & -1 & -2n \\ + * 0 & 0 & -1 & 0 + * \end{pmatrix} + * @f] + * @see @ref orthographicProjection(), @ref Matrix3::projection(), + * @ref Constants::inf() */ static Matrix4 perspectiveProjection(Rad fov, T aspectRatio, T near, T far) { const T xyScale = 2*std::tan(T(fov)/2)*near; @@ -230,6 +341,12 @@ template class Matrix4: public Matrix4x4 { * @param target Location towards which the matrix is oriented * @param up Vector as a guide of which way is up (should not be * the same direction as `target - eye`) + * + * @attention This function transforms an object so it's at @p eye + * position and oriented towards @p target, it does *not* produce + * a camera matrix. If you want to get the same what equivalent + * call to the well-known `gluLookAt()` would produce, invert the + * result using @ref invertedRigid(). */ static Matrix4 lookAt(const Vector3& eye, const Vector3& target, const Vector3& up); @@ -255,7 +372,7 @@ template class Matrix4: public Matrix4x4 { * Creates identity matrix. @p value allows you to specify value on * diagonal. */ - constexpr /*implicit*/ Matrix4(IdentityInitT = IdentityInit, T value = T{1}) + constexpr /*implicit*/ Matrix4(IdentityInitT = IdentityInit, T value = T{1}) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -264,7 +381,7 @@ template class Matrix4: public Matrix4x4 { {} /** @copydoc Matrix::Matrix(ZeroInitT) */ - constexpr explicit Matrix4(ZeroInitT) + constexpr explicit Matrix4(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -273,7 +390,7 @@ template class Matrix4: public Matrix4x4 { {} /** @copydoc Matrix::Matrix(NoInitT) */ - constexpr explicit Matrix4(NoInitT) + constexpr explicit Matrix4(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -282,16 +399,16 @@ template class Matrix4: public Matrix4x4 { {} /** @brief Matrix from column vectors */ - constexpr /*implicit*/ Matrix4(const Vector4& first, const Vector4& second, const Vector4& third, const Vector4& fourth): Matrix4x4(first, second, third, fourth) {} + constexpr /*implicit*/ Matrix4(const Vector4& first, const Vector4& second, const Vector4& third, const Vector4& fourth) noexcept: Matrix4x4(first, second, third, fourth) {} /** @copydoc Matrix::Matrix(const RectangularMatrix&) */ - template constexpr explicit Matrix4(const RectangularMatrix<4, 4, U>& other): Matrix4x4(other) {} + template constexpr explicit Matrix4(const RectangularMatrix<4, 4, U>& other) noexcept: Matrix4x4(other) {} /** @brief Construct matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix4(const U& other): Matrix4x4(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {} /** @brief Copy constructor */ - constexpr Matrix4(const RectangularMatrix<4, 4, T>& other): Matrix4x4(other) {} + constexpr /*implicit*/ Matrix4(const RectangularMatrix<4, 4, T>& other) noexcept: Matrix4x4(other) {} /** * @brief Check whether the matrix represents rigid transformation @@ -447,13 +564,14 @@ template class Matrix4: public Matrix4x4 { * * Unlike in @ref transformVector(), translation is also involved in * the transformation. @f[ - * \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 1 \end{pmatrix} + * \boldsymbol v' = \boldsymbol v''_{xyz} / v''_w ~~~~~~~~~~ \boldsymbol v'' = \begin{pmatrix} v''_x \\ v''_y \\ v''_z \\ v''_w \end{pmatrix} = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 1 \end{pmatrix} \\ * @f] * @see @ref DualQuaternion::transformPoint(), * @ref Matrix3::transformPoint() */ Vector3 transformPoint(const Vector3& vector) const { - return ((*this)*Vector4(vector, T(1))).xyz(); + const Vector4 transformed{(*this)*Vector4(vector, T(1))}; + return transformed.xyz()/transformed.w(); } MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(4, 4, Matrix4) @@ -548,24 +666,27 @@ template Matrix4 Matrix4::orthographicProjection(const Vector2 } template Matrix4 Matrix4::perspectiveProjection(const Vector2& size, const T near, const T far) { - Vector2 xyScale = 2*near/size; - T zScale = T(1.0)/(near-far); - - return {{xyScale.x(), T(0), T(0), T(0)}, - { T(0), xyScale.y(), T(0), T(0)}, - { T(0), T(0), (far+near)*zScale, T(-1)}, - { T(0), T(0), T(2)*far*near*zScale, T(0)}}; + const Vector2 xyScale = 2*near/size; + + if(far == Constants::inf()) { + return {{xyScale.x(), T(0), T(0), T(0)}, + { T(0), xyScale.y(), T(0), T(0)}, + { T(0), T(0), T(-1), T(-1)}, + { T(0), T(0), T(-2)*near, T(0)}}; + } else { + const T zScale = T(1.0)/(near-far); + return {{xyScale.x(), T(0), T(0), T(0)}, + { T(0), xyScale.y(), T(0), T(0)}, + { T(0), T(0), (far+near)*zScale, T(-1)}, + { T(0), T(0), T(2)*far*near*zScale, T(0)}}; + } } template Matrix4 Matrix4::lookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { const Vector3 backward = (eye - target).normalized(); const Vector3 right = cross(up, backward).normalized(); const Vector3 realUp = cross(backward, right); - - return {{ right, T(0)}, - { realUp, T(0)}, - {backward, T(0)}, - { eye, T(1)}}; + return from({right, realUp, backward}, eye); } template inline Matrix3x3 Matrix4::rotation() const { diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 470f72268..290949e14 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -205,13 +205,13 @@ template class Quaternion { * q = [\boldsymbol 0, 1] * @f] */ - constexpr /*implicit*/ Quaternion(IdentityInitT = IdentityInit): _scalar{T(1)} {} + constexpr /*implicit*/ Quaternion(IdentityInitT = IdentityInit) noexcept: _scalar{T(1)} {} /** @brief Construct zero-initialized quaternion */ - constexpr explicit Quaternion(ZeroInitT): _vector{ZeroInit}, _scalar{T{0}} {} + constexpr explicit Quaternion(ZeroInitT) noexcept: _vector{ZeroInit}, _scalar{T{0}} {} /** @brief Construct without initializing the contents */ - explicit Quaternion(NoInitT): _vector{NoInit} {} + explicit Quaternion(NoInitT) noexcept: _vector{NoInit} {} /** * @brief Construct quaternion from vector and scalar @@ -220,7 +220,7 @@ template class Quaternion { * q = [\boldsymbol v, s] * @f] */ - constexpr /*implicit*/ Quaternion(const Vector3& vector, T scalar): _vector(vector), _scalar(scalar) {} + constexpr /*implicit*/ Quaternion(const Vector3& vector, T scalar) noexcept: _vector(vector), _scalar(scalar) {} /** * @brief Construct quaternion from vector @@ -230,7 +230,7 @@ template class Quaternion { * @f] * @see @ref transformVector(), @ref transformVectorNormalized() */ - constexpr explicit Quaternion(const Vector3& vector): _vector(vector), _scalar(T(0)) {} + constexpr explicit Quaternion(const Vector3& vector) noexcept: _vector(vector), _scalar(T(0)) {} /** * @brief Construct dual complex number from another of different type @@ -238,11 +238,14 @@ template class Quaternion { * Performs only default casting on the values, no rounding or anything * else. */ - template constexpr explicit Quaternion(const Quaternion& other): _vector{other._vector}, _scalar{T(other._scalar)} {} + template constexpr explicit Quaternion(const Quaternion& other) noexcept: _vector{other._vector}, _scalar{T(other._scalar)} {} /** @brief Construct quaternion from external representation */ template::from(std::declval()))> constexpr explicit Quaternion(const U& other): Quaternion{Implementation::QuaternionConverter::from(other)} {} + /** @brief Copy constructor */ + constexpr /*implicit*/ Quaternion(const Quaternion&) noexcept = default; + /** @brief Convert quaternion to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { return Implementation::QuaternionConverter::to(*this); @@ -554,10 +557,8 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& d /* Explicit instantiation for commonly used types */ #ifndef DOXYGEN_GENERATING_OUTPUT extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Quaternion&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Quaternion&); #endif -#endif namespace Implementation { diff --git a/src/Magnum/Math/Range.h b/src/Magnum/Math/Range.h index 4161668e9..19c4339c5 100644 --- a/src/Magnum/Math/Range.h +++ b/src/Magnum/Math/Range.h @@ -76,16 +76,13 @@ template class Range { * * Construct zero-size range positioned at origin. */ - constexpr /*implicit*/ Range(ZeroInitT = ZeroInit): _min{ZeroInit}, _max{ZeroInit} {} + constexpr /*implicit*/ Range(ZeroInitT = ZeroInit) noexcept: _min{ZeroInit}, _max{ZeroInit} {} /** @brief Construct without initializing the contents */ - explicit Range(NoInitT): _min{NoInit}, _max{NoInit} {} + explicit Range(NoInitT) noexcept: _min{NoInit}, _max{NoInit} {} /** @brief Construct range from minimal and maximal coordinates */ - constexpr /*implicit*/ Range(const VectorType& min, const VectorType& max): _min{min}, _max{max} {} - - /** @brief Copy constructor */ - constexpr Range(const Range&) = default; + constexpr /*implicit*/ Range(const VectorType& min, const VectorType& max) noexcept: _min{min}, _max{max} {} /** * @brief Construct range from another of different type @@ -97,11 +94,14 @@ template class Range { * Range2D integral(floatingPoint); // {{1, 2}, {-15, 7}} * @endcode */ - template constexpr explicit Range(const Range& other): _min(other._min), _max(other._max) {} + template constexpr explicit Range(const Range& other) noexcept: _min(other._min), _max(other._max) {} /** @brief Construct range from external representation */ template::from(std::declval()))> constexpr explicit Range(const U& other): Range{Implementation::RangeConverter::from(other)} {} + /** @brief Copy constructor */ + constexpr /*implicit*/ Range(const Range&) noexcept = default; + /** @brief Convert range to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { return Implementation::RangeConverter::to(*this); @@ -200,6 +200,7 @@ template class Range { static Type fromSize(const VectorType& min, const VectorType& size) { \ return Range::fromSize(min, size); \ } \ + \ Type translated(const VectorType& vector) const { \ return Range::translated(vector); \ } \ @@ -230,7 +231,7 @@ See @ref Range for more information. template class Range2D: public Range<2, T> { public: /** @copydoc Range(ZeroInitT) */ - constexpr /*implicit*/ Range2D(ZeroInitT = ZeroInit) + constexpr /*implicit*/ Range2D(ZeroInitT = ZeroInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -239,7 +240,7 @@ template class Range2D: public Range<2, T> { {} /** @copydoc Range(NoInitT) */ - explicit Range2D(NoInitT) + explicit Range2D(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -248,13 +249,10 @@ template class Range2D: public Range<2, T> { {} /** @copydoc Range(const VectorType&, const VectorType&) */ - constexpr /*implicit*/ Range2D(const Vector2& min, const Vector2& max): Range<2, T>(min, max) {} - - /** @copydoc Range(const Range&) */ - constexpr /*implicit*/ Range2D(const Range<2, T>& other): Range<2, T>(other) {} + constexpr /*implicit*/ Range2D(const Vector2& min, const Vector2& max) noexcept: Range<2, T>(min, max) {} /** @copydoc Range(const Range&) */ - template constexpr explicit Range2D(const Range2D& other): Range<2, T>(other) {} + template constexpr explicit Range2D(const Range2D& other) noexcept: Range<2, T>(other) {} /** * @brief Construct range from external representation @@ -274,6 +272,9 @@ template class Range2D: public Range<2, T> { #endif {} + /** @copydoc Range(const Range&) */ + constexpr /*implicit*/ Range2D(const Range<2, T>& other) noexcept: Range<2, T>(other) {} + /** * @brief Bottom left corner * @@ -364,7 +365,7 @@ See @ref Range for more information. template class Range3D: public Range<3, T> { public: /** @copydoc Range(ZeroInitT) */ - constexpr /*implicit*/ Range3D(ZeroInitT = ZeroInit) + constexpr /*implicit*/ Range3D(ZeroInitT = ZeroInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -373,7 +374,7 @@ template class Range3D: public Range<3, T> { {} /** @copybrief Range(NoInitT) */ - explicit Range3D(NoInitT) + explicit Range3D(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -382,25 +383,25 @@ template class Range3D: public Range<3, T> { {} /** @copydoc Range(const VectorType&, const VectorType&) */ - constexpr /*implicit*/ Range3D(const Vector3& min, const Vector3& max): Range<3, T>(min, max) {} - - /** @copydoc Range(const Range&) */ - constexpr /*implicit*/ Range3D(const Range<3, T>& other): Range<3, T>(other) {} + constexpr /*implicit*/ Range3D(const Vector3& min, const Vector3& max) noexcept: Range<3, T>(min, max) {} /** @copydoc Range(const Range&) */ - template constexpr explicit Range3D(const Range3D& other): Range<3, T>(other) {} + template constexpr explicit Range3D(const Range3D& other) noexcept: Range<3, T>(other) {} /** * @brief Construct range from external representation * @todoc Remove workaround when Doxygen no longer chokes on that line */ - template::from(std::declval()))> constexpr explicit Range3D(const U& other) + template::from(std::declval()))> constexpr explicit Range3D(const U& other) noexcept #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ : Range<3, T>(Implementation::RangeConverter<3, T, U>::from(other)) #endif {} + /** @copydoc Range(const Range&) */ + constexpr /*implicit*/ Range3D(const Range<3, T>& other) noexcept: Range<3, T>(other) {} + /** * @brief Back bottom left corner * @@ -598,11 +599,9 @@ extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; #endif -#endif }} diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 544f30cc3..e492d8208 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -103,12 +103,12 @@ template class RectangularMatrix { * * @see @ref diagonal() */ - constexpr static RectangularMatrix fromDiagonal(const Vector& diagonal) { + constexpr static RectangularMatrix fromDiagonal(const Vector& diagonal) noexcept { return RectangularMatrix(typename Implementation::GenerateSequence::Type(), diagonal); } /** @brief Construct zero-filled matrix */ - constexpr /*implicit*/ RectangularMatrix(ZeroInitT = ZeroInit) + constexpr /*implicit*/ RectangularMatrix(ZeroInitT = ZeroInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -117,7 +117,7 @@ template class RectangularMatrix { {} /** @brief Construct matrix without initializing the contents */ - explicit RectangularMatrix(NoInitT) + explicit RectangularMatrix(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -132,7 +132,7 @@ template class RectangularMatrix { * * @todo Creating matrix from arbitrary combination of matrices with n rows */ - template constexpr /*implicit*/ RectangularMatrix(const Vector& first, const U&... next): _data{first, next...} { + template constexpr /*implicit*/ RectangularMatrix(const Vector& first, const U&... next) noexcept: _data{first, next...} { static_assert(sizeof...(next)+1 == cols, "Improper number of arguments passed to RectangularMatrix constructor"); } @@ -147,16 +147,13 @@ template class RectangularMatrix { * // integral == {1, 2, -15, 7} * @endcode */ - template constexpr explicit RectangularMatrix(const RectangularMatrix& other): RectangularMatrix(typename Implementation::GenerateSequence::Type(), other) {} + template constexpr explicit RectangularMatrix(const RectangularMatrix& other) noexcept: RectangularMatrix(typename Implementation::GenerateSequence::Type(), other) {} /** @brief Construct matrix from external representation */ template::from(std::declval()))> constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} /** @brief Copy constructor */ - constexpr RectangularMatrix(const RectangularMatrix&) = default; - - /** @brief Assignment operator */ - RectangularMatrix& operator=(const RectangularMatrix&) = default; + constexpr /*implicit*/ RectangularMatrix(const RectangularMatrix&) noexcept = default; /** @brief Convert matrix to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { @@ -194,10 +191,20 @@ template class RectangularMatrix { * Consider using @ref transposed() when accessing rows frequently, as * this is slower than accessing columns due to the way the matrix is * stored. - * @see @ref operator[]() + * @see @ref setRow(), @ref operator[]() */ Vector row(std::size_t row) const; + /** + * @brief Set matrix row + * + * Consider using @ref transposed() when accessing rows frequently, as + * this is slower than accessing columns due to the way the matrix is + * stored. + * @see @ref row(), @ref operator[]() + */ + void setRow(std::size_t row, const Vector& data); + /** @brief Equality comparison */ bool operator==(const RectangularMatrix& other) const { for(std::size_t i = 0; i != cols; ++i) @@ -342,10 +349,33 @@ template class RectangularMatrix { /** * @brief Transposed matrix * - * @see @ref row() + * @f[ + * \boldsymbol{A}^T_ij = \boldsymbol{A}_ji + * @f] + * @see @ref row(), @ref flippedCols(), @ref flippedRows() */ RectangularMatrix transposed() const; + /** + * @brief Matrix with flipped cols + * + * The order of columns is reversed. + * @see @ref transposed(), @ref flippedRows(), @ref Vector::flipped() + */ + constexpr RectangularMatrix flippedCols() const { + return flippedColsInternal(typename Implementation::GenerateReverseSequence::Type{}); + } + + /** + * @brief Matrix with flipped rows + * + * The order of rows is reversed. + * @see @ref transposed(), @ref flippedCols(), @ref Vector::flipped() + */ + constexpr RectangularMatrix flippedRows() const { + return flippedRowsInternal(typename Implementation::GenerateSequence::Type{}); + } + /** * @brief Values on diagonal * @@ -376,11 +406,19 @@ template class RectangularMatrix { private: /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ - template constexpr explicit RectangularMatrix(Implementation::Sequence, const RectangularMatrix& matrix): _data{Vector(matrix[sequence])...} {} + template constexpr explicit RectangularMatrix(Implementation::Sequence, const RectangularMatrix& matrix) noexcept: _data{Vector(matrix[sequence])...} {} /* Implementation for RectangularMatrix::RectangularMatrix(ZeroInitT) and RectangularMatrix::RectangularMatrix(NoInitT) */ /* MSVC 2015 can't handle {} here */ - template constexpr explicit RectangularMatrix(Implementation::Sequence, U): _data{Vector((static_cast(sequence), U{typename U::Init{}}))...} {} + template constexpr explicit RectangularMatrix(Implementation::Sequence, U) noexcept: _data{Vector((static_cast(sequence), U{typename U::Init{}}))...} {} + + template constexpr RectangularMatrix flippedColsInternal(Implementation::Sequence) const { + return {(*this)[sequence]...}; + } + + template constexpr RectangularMatrix flippedRowsInternal(Implementation::Sequence) const { + return {(*this)[sequence].flipped()...}; + } template constexpr Vector diagonalInternal(Implementation::Sequence) const; @@ -485,7 +523,7 @@ template inline RectangularMatrix& matrix) { - RectangularMatrix out; + RectangularMatrix out{NoInit}; for(std::size_t i = 0; i != cols; ++i) out[i] = number/matrix[i]; @@ -524,11 +562,9 @@ template Corrade::Utility::Debug& o extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 2, Float>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 3, Float>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 4, Float>&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 2, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 3, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 4, Double>&); -#endif /* Rectangular matrices */ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 3, Float>&); @@ -537,14 +573,12 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 2, Float>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 4, Float>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 3, Float>&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 3, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 2, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 4, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 2, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 4, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 3, Double>&); -#endif #define MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(cols, rows, ...) \ static __VA_ARGS__& from(T* data) { \ @@ -587,7 +621,13 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili } \ __VA_ARGS__ operator/(T number) const { \ return Math::RectangularMatrix::operator/(number); \ - } + } \ + constexpr __VA_ARGS__ flippedCols() const { \ + return Math::RectangularMatrix::flippedCols(); \ + } \ + constexpr __VA_ARGS__ flippedRows() const { \ + return Math::RectangularMatrix::flippedRows(); \ + } \ #define MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(...) \ template inline __VA_ARGS__ operator*(typename std::common_type::type number, const __VA_ARGS__& matrix) { \ @@ -632,6 +672,11 @@ template inline Vector Rec return out; } +template inline void RectangularMatrix::setRow(std::size_t row, const Vector& data) { + for(std::size_t i = 0; i != cols; ++i) + _data[i][row] = data[i]; +} + template inline RectangularMatrix RectangularMatrix::operator-() const { RectangularMatrix out; @@ -642,7 +687,7 @@ template inline RectangularMatrix template inline RectangularMatrix RectangularMatrix::operator*(const RectangularMatrix& other) const { - RectangularMatrix out; + RectangularMatrix out{ZeroInit}; for(std::size_t col = 0; col != size; ++col) for(std::size_t row = 0; row != rows; ++row) @@ -653,7 +698,7 @@ template template } template inline RectangularMatrix RectangularMatrix::transposed() const { - RectangularMatrix out; + RectangularMatrix out{NoInit}; for(std::size_t col = 0; col != cols; ++col) for(std::size_t row = 0; row != rows; ++row) @@ -718,11 +763,9 @@ template struct ConfigurationValue< extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; -#endif /* Rectangular matrices */ extern template struct MAGNUM_EXPORT ConfigurationValue>; @@ -731,7 +774,6 @@ extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; @@ -739,7 +781,6 @@ extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; #endif -#endif }} diff --git a/src/Magnum/Math/Test/AngleTest.cpp b/src/Magnum/Math/Test/AngleTest.cpp index 43843e70a..f27d646e9 100644 --- a/src/Magnum/Math/Test/AngleTest.cpp +++ b/src/Magnum/Math/Test/AngleTest.cpp @@ -25,6 +25,7 @@ #include #include +#include #include "Magnum/Math/Angle.h" @@ -34,81 +35,69 @@ struct AngleTest: Corrade::TestSuite::Tester { explicit AngleTest(); void construct(); + void constructDefault(); void constructNoInit(); + void constructConversion(); + void constructCopy(); + void literals(); void conversion(); void debugDeg(); void debugRad(); + void configurationDeg(); + void configurationRad(); }; typedef Math::Deg Deg; typedef Math::Rad Rad; -#ifndef MAGNUM_TARGET_GLES typedef Math::Deg Degd; typedef Math::Rad Radd; -#endif AngleTest::AngleTest() { addTests({&AngleTest::construct, + &AngleTest::constructDefault, &AngleTest::constructNoInit, + &AngleTest::constructConversion, + &AngleTest::constructCopy, + &AngleTest::literals, &AngleTest::conversion, &AngleTest::debugDeg, - &AngleTest::debugRad}); + &AngleTest::debugRad, + &AngleTest::configurationDeg, + &AngleTest::configurationRad}); } void AngleTest::construct() { - /* Default constructor */ + constexpr Deg b(25.0); + CORRADE_COMPARE(Float(b), 25.0f); + constexpr Radd n(3.14); + CORRADE_COMPARE(Double(n), 3.14); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void AngleTest::constructDefault() { constexpr Deg m1; constexpr Deg m2{ZeroInit}; CORRADE_COMPARE(Float(m1), 0.0f); CORRADE_COMPARE(Float(m2), 0.0f); - #ifndef MAGNUM_TARGET_GLES constexpr Radd a1; constexpr Radd a2{ZeroInit}; CORRADE_COMPARE(Double(a1), 0.0); CORRADE_COMPARE(Double(a2), 0.0); - #else - constexpr Rad a1; - constexpr Rad a2{ZeroInit}; - CORRADE_COMPARE(Float(a1), 0.0f); - CORRADE_COMPARE(Float(a2), 0.0f); - #endif - - /* Value constructor */ - constexpr Deg b(25.0); - CORRADE_COMPARE(Float(b), 25.0f); - #ifndef MAGNUM_TARGET_GLES - constexpr Radd n(3.14); - CORRADE_COMPARE(Double(n), 3.14); - #else - constexpr Rad n(3.14); - CORRADE_COMPARE(Float(n), 3.14f); - #endif - - /* Copy constructor */ - constexpr Deg c(b); - CORRADE_COMPARE(c, b); - #ifndef MAGNUM_TARGET_GLES - constexpr Radd o(n); - CORRADE_COMPARE(o, n); - #else - constexpr Rad o(n); - CORRADE_COMPARE(o, n); - #endif - - /* Conversion operator */ - constexpr Rad p(n); - CORRADE_COMPARE(Float(p), 3.14f); - #ifndef MAGNUM_TARGET_GLES - constexpr Degd d(b); - CORRADE_COMPARE(Double(d), 25.0); - #else - constexpr Deg d(b); - CORRADE_COMPARE(Float(d), 25.0f); - #endif + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void AngleTest::constructNoInit() { @@ -116,27 +105,71 @@ void AngleTest::constructNoInit() { Rad b{3.14f}; new(&a) Deg{NoInit}; new(&b) Rad{NoInit}; - CORRADE_COMPARE(Float(a), 25.0f); - CORRADE_COMPARE(Float(b), 3.14f); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 + /* The warning is reported for both debug and release build */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + #ifdef __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + #endif + CORRADE_COMPARE(Float(a), 25.0f); + CORRADE_COMPARE(Float(b), 3.14f); + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 + #pragma GCC diagnostic pop + #endif + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void AngleTest::constructConversion() { + constexpr Deg a(25.0); + constexpr Radd b(3.14); + + constexpr Rad c(b); + CORRADE_COMPARE(Float(c), 3.14f); + constexpr Degd d(a); + CORRADE_COMPARE(Double(d), 25.0); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void AngleTest::constructCopy() { + constexpr Deg a(25.0); + constexpr Radd b(3.14); + + constexpr Deg c(a); + CORRADE_COMPARE(c, a); + constexpr Radd d(b); + CORRADE_COMPARE(d, b); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void AngleTest::literals() { using namespace Literals; - #ifndef MAGNUM_TARGET_GLES constexpr auto a = 25.0_deg; CORRADE_VERIFY((std::is_same::value)); CORRADE_COMPARE(Double(a), 25.0); - #endif constexpr auto b = 25.0_degf; CORRADE_VERIFY((std::is_same::value)); CORRADE_COMPARE(Float(b), 25.0f); - #ifndef MAGNUM_TARGET_GLES constexpr auto m = 3.14_rad; CORRADE_VERIFY((std::is_same::value)); CORRADE_COMPARE(Double(m), 3.14); - #endif constexpr auto n = 3.14_radf; CORRADE_VERIFY((std::is_same::value)); CORRADE_COMPARE(Float(n), 3.14f); @@ -175,6 +208,28 @@ void AngleTest::debugRad() { CORRADE_COMPARE(o.str(), "Rad(-1.5708)\n"); } +void AngleTest::configurationDeg() { + Corrade::Utility::Configuration c; + + Deg angle{25.3f}; + std::string value("25.3"); + + c.setValue("angle", angle); + CORRADE_COMPARE(c.value("angle"), value); + CORRADE_COMPARE(c.value("angle"), angle); +} + +void AngleTest::configurationRad() { + Corrade::Utility::Configuration c; + + Rad angle{3.14159f}; + std::string value("3.14159"); + + c.setValue("angle", angle); + CORRADE_COMPARE(c.value("angle"), value); + CORRADE_COMPARE(c.value("angle"), angle); +} + }}} CORRADE_TEST_MAIN(Magnum::Math::Test::AngleTest) diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp new file mode 100644 index 000000000..04afa111d --- /dev/null +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -0,0 +1,253 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Ashwin Ravichandran + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include + +#include "Magnum/Math/Bezier.h" +#include "Magnum/Math/Vector2.h" +#include "Magnum/Math/Functions.h" + +namespace Magnum { namespace Math { namespace Test { + +typedef Math::Vector2 Vector2; +typedef Math::Vector2 Vector2d; +typedef Math::Bezier<1, 2, Float> LinearBezier2D; +typedef Math::QuadraticBezier2D QuadraticBezier2D; +typedef Math::QuadraticBezier2D QuadraticBezier2Dd; +typedef Math::CubicBezier2D CubicBezier2D; + +struct BezierTest : Corrade::TestSuite::Tester { + explicit BezierTest(); + + void construct(); + void constructDefault(); + void constructNoInit(); + void constructConversion(); + void constructCopy(); + + void data(); + + void compare(); + + void valueLinear(); + void valueQuadratic(); + void valueCubic(); + void subdivideLinear(); + void subdivideQuadratic(); + void subdivideCubic(); + + void debug(); + void configuration(); +}; + +BezierTest::BezierTest() { + addTests({&BezierTest::construct, + &BezierTest::constructDefault, + &BezierTest::constructNoInit, + &BezierTest::constructConversion, + &BezierTest::constructCopy, + + &BezierTest::data, + + &BezierTest::compare, + + &BezierTest::valueLinear, + &BezierTest::valueQuadratic, + &BezierTest::valueCubic, + &BezierTest::subdivideLinear, + &BezierTest::subdivideQuadratic, + &BezierTest::subdivideCubic, + + &BezierTest::debug, + &BezierTest::configuration}); +} + +void BezierTest::construct() { + /* The constructor should be implicit */ + constexpr QuadraticBezier2D a = {Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}}; + CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void BezierTest::constructDefault() { + constexpr QuadraticBezier2D a; + constexpr QuadraticBezier2D b{ZeroInit}; + CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{}, Vector2{}, Vector2{}})); + CORRADE_COMPARE(b, (QuadraticBezier2D{Vector2{}, Vector2{}, Vector2{}})); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void BezierTest::constructNoInit() { + QuadraticBezier2D a{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}}; + new(&a) QuadraticBezier2D{NoInit}; + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void BezierTest::constructConversion() { + constexpr QuadraticBezier2Dd a{Vector2d{0.5, 1.0}, Vector2d{1.1, 0.3}, Vector2d{0.1, 1.2}}; + constexpr QuadraticBezier2D b{a}; + + CORRADE_COMPARE(b, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void BezierTest::constructCopy() { + constexpr QuadraticBezier2D a{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}}; + constexpr QuadraticBezier2D b{a}; + CORRADE_COMPARE(b, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); +} + +void BezierTest::data() { + QuadraticBezier2D a{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}}; + a[0] = {}; + a[2] = {0.7f, 20.3f}; + + CORRADE_COMPARE(a[0], (Vector2{0.0f, 0.0f})); + CORRADE_COMPARE(a[2], (Vector2{0.7f, 20.3f})); + CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{0.0f, 0.0f}, Vector2{1.1f, 0.3f}, Vector2{0.7f, 20.3f}})); + + constexpr QuadraticBezier2D b{Vector2{3.5f, 0.1f}, Vector2{1.3f, 10.3f}, Vector2{0.0f, -1.2f}}; + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */ + constexpr + #endif + Vector2 c = b[2]; + CORRADE_COMPARE(c, (Vector2{0.0f, -1.2f})); +} + +void BezierTest::compare() { + CORRADE_VERIFY((QuadraticBezier2D{Vector2{0.5f, 1.0f + TypeTraits::epsilon()/2}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}} == QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); + CORRADE_VERIFY((QuadraticBezier2D{Vector2{0.5f, 1.1f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.0f + TypeTraits::epsilon()*2}} != QuadraticBezier2D{Vector2{0.5f, 1.1f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.0f}})); +} + +void BezierTest::valueLinear() { + LinearBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{20.0f, 4.0f}}; + + CORRADE_COMPARE(bezier.value(0.2f), (Vector2{4.0f, 0.8f})); + CORRADE_COMPARE(bezier.value(0.5f), (Vector2{10.0f, 2.0f})); + CORRADE_COMPARE(bezier.value(0.2f), Math::lerp(bezier[0], bezier[1], 0.2f)); +} + +void BezierTest::valueQuadratic() { + QuadraticBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}}; + + CORRADE_COMPARE(bezier.value(0.2f), (Vector2{4.0f, 4.96f})); + CORRADE_COMPARE(bezier.value(0.5f), (Vector2{10.0f, 8.5f})); + CORRADE_VERIFY(bezier.value(0.2f) != Math::lerp(bezier[0], bezier[2], 0.2f)); +} + +void BezierTest::valueCubic() { + Vector2 p0(0.0f, 0.0f), p1(10.0f, 15.0f), p2(20.0f, 4.0f), p3(5.0f, -20.0f); + CubicBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}, Vector2{5.0f, -20.0f}}; + + CORRADE_COMPARE(bezier.value(0.2f), (Vector2{5.8f, 5.984f})); + CORRADE_COMPARE(bezier.value(0.5f), (Vector2{11.875f, 4.625f})); + CORRADE_VERIFY(bezier.value(0.2f) != Math::lerp(bezier[0], bezier[3], 0.2f)); +} + +void BezierTest::subdivideLinear() { + LinearBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{20.0f, 4.0f}}; + + LinearBezier2D left, right; + std::tie(left, right) = bezier.subdivide(0.25f); + + CORRADE_COMPARE(left[0], bezier[0]); + CORRADE_COMPARE(left[1], right[0]); + CORRADE_COMPARE(right[1], bezier[1]); + CORRADE_COMPARE(left.value(0.8f), bezier.value(0.2f)); + CORRADE_COMPARE(right.value(0.33333f), bezier.value(0.5f)); + CORRADE_COMPARE(left, (LinearBezier2D{Vector2{0.0f, 0.0f}, Vector2{5.0f, 1.0f}})); + CORRADE_COMPARE(right, (LinearBezier2D{Vector2{5.0f, 1.0f}, Vector2{20.0f, 4.0f}})); +} + +void BezierTest::subdivideQuadratic() { + QuadraticBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}}; + + QuadraticBezier2D left, right; + std::tie(left, right) = bezier.subdivide(0.25f); + + CORRADE_COMPARE(left[0], bezier[0]); + CORRADE_COMPARE(left[2], right[0]); + CORRADE_COMPARE(right[2], bezier[2]); + CORRADE_COMPARE(left.value(0.8f), bezier.value(0.2f)); + CORRADE_COMPARE(right.value(0.33333f), bezier.value(0.5f)); + CORRADE_COMPARE(left, (QuadraticBezier2D{Vector2{0.0f, 0.0f}, Vector2{2.5f, 3.75f}, Vector2{5.0f, 5.875f}})); + CORRADE_COMPARE(right, (QuadraticBezier2D{Vector2{5.0f, 5.875f}, Vector2{12.5f, 12.25f}, Vector2{20.0f, 4.0f}})); +} + +void BezierTest::subdivideCubic() { + CubicBezier2D bezier{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}, Vector2{5.0f, -20.0f}}; + + CubicBezier2D left, right; + std::tie(left, right) = bezier.subdivide(0.25f); + + CORRADE_COMPARE(left[0], bezier[0]); + CORRADE_COMPARE(left[3], right[0]); + CORRADE_COMPARE(right[3], bezier[3]); + CORRADE_COMPARE(left.value(0.8f), bezier.value(0.2f)); + CORRADE_COMPARE(right.value(0.33333f), bezier.value(0.5f)); + CORRADE_COMPARE(left, (CubicBezier2D{Vector2{0.0f, 0.0f}, Vector2{2.5f, 3.75f}, Vector2{5.0f, 5.875f}, Vector2{7.10938f, 6.57812f}})); + CORRADE_COMPARE(right, (CubicBezier2D{Vector2{7.10938f, 6.57812f}, Vector2{13.4375f, 8.6875f}, Vector2{16.25f, -2.0f}, Vector2{5.0f, -20.0f}})); +} + +void BezierTest::debug() { + std::ostringstream out; + Debug(&out) << CubicBezier2D{Vector2{0.0f, 1.0f}, Vector2{1.5f, -0.3f}, Vector2{2.1f, 0.5f}, Vector2{0.0f, 2.0f}}; + CORRADE_COMPARE(out.str(), "Bezier({0, 1}, {1.5, -0.3}, {2.1, 0.5}, {0, 2})\n"); +} + +void BezierTest::configuration() { + Corrade::Utility::Configuration c; + + CubicBezier2D bezier{Vector2{0.0f, 1.0f}, Vector2{1.5f, -0.3f}, Vector2{2.1f, 0.5f}, Vector2{0.0f, 2.0f}}; + std::string value("0 1 1.5 -0.3 2.1 0.5 0 2"); + + c.setValue("bezier", bezier); + CORRADE_COMPARE(c.value("bezier"), value); + CORRADE_COMPARE(c.value("bezier"), bezier); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Math::Test::BezierTest) diff --git a/src/Magnum/Math/Test/BoolVectorTest.cpp b/src/Magnum/Math/Test/BoolVectorTest.cpp index 4a6d8c78d..0325a644d 100644 --- a/src/Magnum/Math/Test/BoolVectorTest.cpp +++ b/src/Magnum/Math/Test/BoolVectorTest.cpp @@ -43,6 +43,7 @@ struct BoolVectorTest: Corrade::TestSuite::Tester { void compare(); void compareUndefined(); + void convertBool(); void all(); void none(); void any(); @@ -70,6 +71,7 @@ BoolVectorTest::BoolVectorTest() { &BoolVectorTest::compare, &BoolVectorTest::compareUndefined, + &BoolVectorTest::convertBool, &BoolVectorTest::all, &BoolVectorTest::none, &BoolVectorTest::any, @@ -83,6 +85,8 @@ BoolVectorTest::BoolVectorTest() { void BoolVectorTest::construct() { constexpr BoolVector19 a = {0xa5, 0x5f, 0x07}; CORRADE_COMPARE(a, BoolVector19(0xa5, 0x5f, 0x07)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void BoolVectorTest::constructDefault() { @@ -90,12 +94,22 @@ void BoolVectorTest::constructDefault() { constexpr BoolVector19 b{ZeroInit}; CORRADE_COMPARE(a, BoolVector19(0x00, 0x00, 0x00)); CORRADE_COMPARE(b, BoolVector19(0x00, 0x00, 0x00)); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void BoolVectorTest::constructNoInit() { BoolVector19 a{0xa5, 0x5f, 0x07}; new(&a) BoolVector19{NoInit}; - CORRADE_COMPARE(a, BoolVector19(0xa5, 0x5f, 0x07)); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, BoolVector19(0xa5, 0x5f, 0x07)); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void BoolVectorTest::constructOneValue() { @@ -106,6 +120,8 @@ void BoolVectorTest::constructOneValue() { CORRADE_COMPARE(b, BoolVector19(0xff, 0xff, 0x07)); CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void BoolVectorTest::constructOneElement() { @@ -113,12 +129,17 @@ void BoolVectorTest::constructOneElement() { constexpr BoolVector1 a = 0x01; CORRADE_COMPARE(a, BoolVector1(0x01)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void BoolVectorTest::constructCopy() { constexpr BoolVector19 a = {0xa5, 0x5f, 0x07}; constexpr BoolVector19 b(a); CORRADE_COMPARE(b, BoolVector19(0xa5, 0x5f, 0x07)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void BoolVectorTest::data() { @@ -174,6 +195,15 @@ void BoolVectorTest::compareUndefined() { CORRADE_VERIFY(a != c); } +void BoolVectorTest::convertBool() { + /* The ! operation should *just work* using the bool conversion operator */ + CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0x07)); + CORRADE_VERIFY(!BoolVector19(0xff, 0xff, 0x04)); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void BoolVectorTest::all() { CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0x07).all()); diff --git a/src/Magnum/Math/Test/CMakeLists.txt b/src/Magnum/Math/Test/CMakeLists.txt index 9eeba4cfb..9f93ec1e1 100644 --- a/src/Magnum/Math/Test/CMakeLists.txt +++ b/src/Magnum/Math/Test/CMakeLists.txt @@ -51,6 +51,8 @@ corrade_add_test(MathDualComplexTest DualComplexTest.cpp LIBRARIES MagnumMathTes corrade_add_test(MathQuaternionTest QuaternionTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathDualQuaternionTest DualQuaternionTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathBezierTest BezierTest.cpp LIBRARIES MagnumMathTestLib) + set_property(TARGET MathVectorTest MathMatrixTest diff --git a/src/Magnum/Math/Test/ColorTest.cpp b/src/Magnum/Math/Test/ColorTest.cpp index 8140b757a..014a2cb8a 100644 --- a/src/Magnum/Math/Test/ColorTest.cpp +++ b/src/Magnum/Math/Test/ColorTest.cpp @@ -29,20 +29,54 @@ #include "Magnum/Math/Color.h" -namespace Magnum { namespace Math { namespace Test { +struct Vec3 { + float x, y, z; +}; + +struct Vec4 { + float x, y, z, w; +}; + +namespace Magnum { namespace Math { + +namespace Implementation { + +template<> struct VectorConverter<3, float, Vec3> { + constexpr static Vector<3, Float> from(const Vec3& other) { + return {other.x, other.y, other.z}; + } + + constexpr static Vec3 to(const Vector<3, Float>& other) { + return {other[0], other[1], other[2]}; + } +}; + +template<> struct VectorConverter<4, float, Vec4> { + constexpr static Vector<4, Float> from(const Vec4& other) { + return {other.x, other.y, other.z, other.w}; + } + + constexpr static Vec4 to(const Vector<4, Float>& other) { + return {other[0], other[1], other[2], other[3]}; + } +}; + +} + +namespace Test { struct ColorTest: Corrade::TestSuite::Tester { explicit ColorTest(); void construct(); void constructDefault(); - void constructZero(); void constructNoInit(); void constructOneValue(); void constructParts(); void constructConversion(); void constructNormalization(); void constructCopy(); + void convert(); void literals(); @@ -80,13 +114,13 @@ using namespace Literals; ColorTest::ColorTest() { addTests({&ColorTest::construct, &ColorTest::constructDefault, - &ColorTest::constructZero, &ColorTest::constructNoInit, &ColorTest::constructOneValue, &ColorTest::constructParts, &ColorTest::constructConversion, &ColorTest::constructNormalization, &ColorTest::constructCopy, + &ColorTest::convert, &ColorTest::literals, @@ -121,6 +155,9 @@ void ColorTest::construct() { constexpr Color4ub d = {10, 25, 176}; CORRADE_COMPARE(c, Vector4(1.0f, 0.5f, 0.75f, 1.0f)); CORRADE_COMPARE(d, Math::Vector4(10, 25, 176, 255)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ColorTest::constructDefault() { @@ -129,17 +166,18 @@ void ColorTest::constructDefault() { CORRADE_COMPARE(a1, Color3(0.0f, 0.0f, 0.0f)); CORRADE_COMPARE(a2, Color3(0.0f, 0.0f, 0.0f)); - constexpr Color4 b; + constexpr Color4 b1; + constexpr Color4 b2{Math::ZeroInit}; + CORRADE_COMPARE(b1, Color4(0.0f, 0.0f, 0.0f, 0.0f)); + CORRADE_COMPARE(b2, Color4(0.0f, 0.0f, 0.0f, 0.0f)); + constexpr Color4ub c; - CORRADE_COMPARE(b, Color4(0.0f, 0.0f, 0.0f, 0.0f)); CORRADE_COMPARE(c, Color4ub(0, 0, 0, 0)); -} -void ColorTest::constructZero() { - constexpr Color3 a{Math::ZeroInit}; - constexpr Color4 b{Math::ZeroInit}; - CORRADE_COMPARE(a, Color3(0.0f, 0.0f, 0.0f)); - CORRADE_COMPARE(b, Color4(0.0f, 0.0f, 0.0f, 0.0f)); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ColorTest::constructNoInit() { @@ -147,8 +185,16 @@ void ColorTest::constructNoInit() { Color4 b{1.0f, 0.5f, 0.75f, 0.5f}; new(&a) Color3{Math::NoInit}; new(&b) Color4{Math::NoInit}; - CORRADE_COMPARE(a, (Color3{1.0f, 0.5f, 0.75f})); - CORRADE_COMPARE(b, (Color4{1.0f, 0.5f, 0.75f, 0.5f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, (Color3{1.0f, 0.5f, 0.75f})); + CORRADE_COMPARE(b, (Color4{1.0f, 0.5f, 0.75f, 0.5f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ColorTest::constructOneValue() { @@ -167,6 +213,9 @@ void ColorTest::constructOneValue() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ColorTest::constructParts() { @@ -181,6 +230,8 @@ void ColorTest::constructParts() { constexpr Color4ub e = c; CORRADE_COMPARE(d, Color4(1.0f, 0.5f, 0.75f, 1.0f)); CORRADE_COMPARE(e, Color4ub(10, 25, 176, 255)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ColorTest::constructConversion() { @@ -195,6 +246,9 @@ void ColorTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ColorTest::constructNormalization() { @@ -221,6 +275,48 @@ void ColorTest::constructCopy() { #endif Color4 d(c); CORRADE_COMPARE(d, Color4(1.0f, 0.5f, 0.75f, 0.25f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); +} + +void ColorTest::convert() { + constexpr Vec3 a3{1.5f, 2.0f, -3.5f}; + constexpr Color3 b3{1.5f, 2.0f, -3.5f}; + + #ifndef CORRADE_MSVC2015_COMPATIBILITY + constexpr /* No idea what's wrong. For Vector3 it "just works" */ + #endif + Color3 c3(a3); + CORRADE_COMPARE(c3, b3); + + constexpr Vec3 d3(b3); + CORRADE_COMPARE(d3.x, a3.x); + CORRADE_COMPARE(d3.y, a3.y); + CORRADE_COMPARE(d3.z, a3.z); + + constexpr Vec4 a4{1.5f, 2.0f, -3.5f, -0.5f}; + constexpr Color4 b4{1.5f, 2.0f, -3.5f, -0.5f}; + + #ifndef CORRADE_MSVC2015_COMPATIBILITY + constexpr /* No idea what's wrong. For Vector4 it "just works" */ + #endif + Color4 c4(a4); + CORRADE_COMPARE(c4, b4); + + constexpr Vec4 d4(b4); + CORRADE_COMPARE(d4.x, a4.x); + CORRADE_COMPARE(d4.y, a4.y); + CORRADE_COMPARE(d4.z, a4.z); + CORRADE_COMPARE(d4.w, a4.w); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); } void ColorTest::literals() { @@ -233,8 +329,8 @@ void ColorTest::literals() { CORRADE_COMPARE(b, (Color4ub{0x33, 0xb2, 0x7f, 0xcc})); /* Not constexpr yet */ - CORRADE_COMPARE(0x33b27f_rgbf, (Color3{0.2, 0.698039f, 0.498039f})); - CORRADE_COMPARE(0x33b27fcc_rgbaf, (Color4{0.2, 0.698039f, 0.498039f, 0.8f})); + CORRADE_COMPARE(0x33b27f_rgbf, (Color3{0.2f, 0.698039f, 0.498039f})); + CORRADE_COMPARE(0x33b27fcc_rgbaf, (Color4{0.2f, 0.698039f, 0.498039f, 0.8f})); } void ColorTest::colors() { diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index c24dff8d4..8c46d13e1 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -68,6 +68,7 @@ struct ComplexTest: Corrade::TestSuite::Tester { void compare(); void isNormalized(); + template void isNormalizedEpsilon(); void addSubtract(); void negated(); @@ -78,6 +79,7 @@ struct ComplexTest: Corrade::TestSuite::Tester { void dotSelf(); void length(); void normalized(); + template void normalizedIterative(); void conjugated(); void inverted(); @@ -103,6 +105,8 @@ ComplexTest::ComplexTest() { &ComplexTest::compare, &ComplexTest::isNormalized, + &ComplexTest::isNormalizedEpsilon, + &ComplexTest::isNormalizedEpsilon, &ComplexTest::addSubtract, &ComplexTest::negated, @@ -112,9 +116,13 @@ ComplexTest::ComplexTest() { &ComplexTest::dot, &ComplexTest::dotSelf, &ComplexTest::length, - &ComplexTest::normalized, + &ComplexTest::normalized}); - &ComplexTest::conjugated, + addRepeatedTests({ + &ComplexTest::normalizedIterative, + &ComplexTest::normalizedIterative}, 1000); + + addTests({&ComplexTest::conjugated, &ComplexTest::inverted, &ComplexTest::invertedNormalized, @@ -141,6 +149,8 @@ void ComplexTest::construct() { constexpr Float c = a.imaginary(); CORRADE_COMPARE(b, 0.5f); CORRADE_COMPARE(c, -3.7f); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ComplexTest::constructIdentity() { @@ -150,17 +160,29 @@ void ComplexTest::constructIdentity() { CORRADE_COMPARE(b, Complex(1.0f, 0.0f)); CORRADE_COMPARE(a.length(), 1.0f); CORRADE_COMPARE(b.length(), 1.0f); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ComplexTest::constructZero() { constexpr Complex a{ZeroInit}; CORRADE_COMPARE(a, Complex(0.0f, 0.0f)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ComplexTest::constructNoInit() { Complex a{0.5f, -3.7f}; new(&a) Complex{NoInit}; - CORRADE_COMPARE(a, Complex(0.5f, -3.7f)); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Complex(0.5f, -3.7f)); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ComplexTest::constructFromVector() { @@ -175,6 +197,8 @@ void ComplexTest::constructFromVector() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ComplexTest::constructConversion() { @@ -187,12 +211,17 @@ void ComplexTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void ComplexTest::constructCopy() { constexpr Complex a(2.5f, -5.0f); constexpr Complex b(a); CORRADE_COMPARE(b, Complex(2.5f, -5.0f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void ComplexTest::convert() { @@ -229,6 +258,13 @@ void ComplexTest::isNormalized() { CORRADE_VERIFY(Complex::rotation(Deg(23.0f)).isNormalized()); } +template void ComplexTest::isNormalizedEpsilon() { + setTestCaseName(std::string{"isNormalizedEpsilon<"} + TypeTraits::name() + ">"); + + CORRADE_VERIFY((Math::Complex{T(0.801775644243754) + TypeTraits::epsilon()/T(2.0), T(0.597625146975521)}.isNormalized())); + CORRADE_VERIFY(!(Math::Complex{T(0.801775644243754) + TypeTraits::epsilon()*T(2.0), T(0.597625146975521)}.isNormalized())); +} + void ComplexTest::addSubtract() { Complex a( 1.7f, -3.7f); Complex b(-3.6f, 0.2f); @@ -286,6 +322,18 @@ void ComplexTest::normalized() { CORRADE_COMPARE(a.normalized().length(), 1.0f); } +template void ComplexTest::normalizedIterative() { + setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits::name() + ">"); + + auto a = Math::Complex::rotation(Math::Deg{T(36.7)}); + for(std::size_t i = 0; i != testCaseRepeatId(); ++i) { + a = Math::Complex::rotation(Math::Deg{T(87.1)})*a; + a = a.normalized(); + } + + CORRADE_VERIFY(a.isNormalized()); +} + void ComplexTest::conjugated() { CORRADE_COMPARE(Complex(-3.0f, 4.5f).conjugated(), Complex(-3.0f, -4.5f)); } diff --git a/src/Magnum/Math/Test/ConstantsTest.cpp b/src/Magnum/Math/Test/ConstantsTest.cpp index 578efa578..4ac226d81 100644 --- a/src/Magnum/Math/Test/ConstantsTest.cpp +++ b/src/Magnum/Math/Test/ConstantsTest.cpp @@ -34,34 +34,20 @@ namespace Magnum { namespace Math { namespace Test { struct ConstantsTest: Corrade::TestSuite::Tester { explicit ConstantsTest(); - void constants(); - void specials(); - - private: - template void _constants(); - template void _specials(); + template void constants(); + template void specials(); }; ConstantsTest::ConstantsTest() { - addTests({&ConstantsTest::constants, - &ConstantsTest::specials}); + addTests({&ConstantsTest::constants, + &ConstantsTest::constants, + &ConstantsTest::specials, + &ConstantsTest::specials}); } -void ConstantsTest::constants() { - _constants(); - #ifndef MAGNUM_TARGET_GLES - _constants(); - #endif -} +template void ConstantsTest::constants() { + setTestCaseName(std::is_same::value ? "constants" : "constants"); -void ConstantsTest::specials() { - _specials(); - #ifndef MAGNUM_TARGET_GLES - _specials(); - #endif -} - -template void ConstantsTest::_constants() { constexpr T a = Constants::sqrt2(); constexpr T b = Constants::sqrt3(); CORRADE_COMPARE(Math::pow<2>(a), T(2)); @@ -77,7 +63,9 @@ template void ConstantsTest::_constants() { CORRADE_COMPARE(std::log(f), T(1)); } -template void ConstantsTest::_specials() { +template void ConstantsTest::specials() { + setTestCaseName(std::is_same::value ? "specials" : "specials"); + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* NaN is not constexpr */ constexpr #endif diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index 892f9d36c..026a5ca56 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -67,12 +67,15 @@ struct DualComplexTest: Corrade::TestSuite::Tester { void convert(); void isNormalized(); + template void isNormalizedEpsilonRotation(); + template void isNormalizedEpsilonTranslation(); void multiply(); void lengthSquared(); void length(); void normalized(); + template void normalizedIterative(); void complexConjugated(); void dualConjugated(); @@ -108,14 +111,22 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::convert, &DualComplexTest::isNormalized, + &DualComplexTest::isNormalizedEpsilonRotation, + &DualComplexTest::isNormalizedEpsilonRotation, + &DualComplexTest::isNormalizedEpsilonTranslation, + &DualComplexTest::isNormalizedEpsilonTranslation, &DualComplexTest::multiply, &DualComplexTest::lengthSquared, &DualComplexTest::length, - &DualComplexTest::normalized, + &DualComplexTest::normalized}); - &DualComplexTest::complexConjugated, + addRepeatedTests({ + &DualComplexTest::normalizedIterative, + &DualComplexTest::normalizedIterative}, 1000); + + addTests({&DualComplexTest::complexConjugated, &DualComplexTest::dualConjugated, &DualComplexTest::conjugated, &DualComplexTest::inverted, @@ -141,6 +152,8 @@ void DualComplexTest::construct() { constexpr DualComplex d(Complex(-1.0f, 2.5f)); CORRADE_COMPARE(d, DualComplex({-1.0f, 2.5f}, {0.0f, 0.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualComplexTest::constructIdentity() { @@ -150,17 +163,29 @@ void DualComplexTest::constructIdentity() { CORRADE_COMPARE(b, DualComplex({1.0f, 0.0f}, {0.0f, 0.0f})); CORRADE_COMPARE(a.length(), 1.0f); CORRADE_COMPARE(b.length(), 1.0f); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualComplexTest::constructZero() { constexpr DualComplex a{ZeroInit}; CORRADE_COMPARE(a, DualComplex({0.0f, 0.0f}, {0.0f, 0.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualComplexTest::constructNoInit() { DualComplex a{{-1.0f, 2.5f}, {3.0f, -7.5f}}; new(&a) DualComplex{NoInit}; - CORRADE_COMPARE(a, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualComplexTest::constructFromVector() { @@ -169,6 +194,8 @@ void DualComplexTest::constructFromVector() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualComplexTest::constructConversion() { @@ -181,6 +208,8 @@ void DualComplexTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualComplexTest::constructCopy() { @@ -190,6 +219,9 @@ void DualComplexTest::constructCopy() { #endif DualComplex b(a); CORRADE_COMPARE(b, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void DualComplexTest::convert() { @@ -221,6 +253,21 @@ void DualComplexTest::isNormalized() { CORRADE_VERIFY((DualComplex::rotation(Deg(23.0f))*DualComplex::translation({6.0f, 3.0f})).isNormalized()); } +template void DualComplexTest::isNormalizedEpsilonRotation() { + setTestCaseName(std::string{"isNormalizedEpsilonRotation<"} + TypeTraits::name() + ">"); + + CORRADE_VERIFY((Math::DualComplex{{T(0.801775644243754) + TypeTraits::epsilon()/T(2.0), T(0.597625146975521)}, {T(8018055.25501103), T(5975850.58193309)}}.isNormalized())); + CORRADE_VERIFY(!(Math::DualComplex{{T(0.801775644243754) + TypeTraits::epsilon()*T(2.0), T(0.597625146975521)}, {T(8018055.25501103), T(5975850.58193309)}}.isNormalized())); +} + +template void DualComplexTest::isNormalizedEpsilonTranslation() { + setTestCaseName(std::string{"isNormalizedEpsilonTranslation<"} + TypeTraits::name() + ">"); + + /* Translation does not affect normalization */ + CORRADE_VERIFY((Math::DualComplex{{T(0.801775644243754), T(0.597625146975521)}, {T(8018055.25501103), T(20.5)}}.isNormalized())); + CORRADE_VERIFY((Math::DualComplex{{T(0.801775644243754), T(0.597625146975521)}, {T(8018055.25501103), T(-200000000.0)}}.isNormalized())); +} + void DualComplexTest::multiply() { DualComplex a({-1.5f, 2.0f}, { 3.0f, -6.5f}); DualComplex b({ 2.0f, -7.5f}, {-0.5f, 1.0f});; @@ -244,6 +291,28 @@ void DualComplexTest::normalized() { CORRADE_COMPARE(a.normalized(), b); } +namespace { + template struct NormalizedIterativeData; + template<> struct NormalizedIterativeData { + static Math::Vector2 translation() { return {10000.0f, -50.0f}; } + }; + template<> struct NormalizedIterativeData { + static Math::Vector2 translation() { return {10000000.0, -500.0}; } + }; +} + +template void DualComplexTest::normalizedIterative() { + setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits::name() + ">"); + + auto a = Math::DualComplex::rotation(Math::Deg{T(36.7)})*Math::DualComplex::translation(NormalizedIterativeData::translation()); + for(std::size_t i = 0; i != testCaseRepeatId(); ++i) { + a = Math::DualComplex::rotation(Math::Deg{T(87.1)})*a; + a = a.normalized(); + } + + CORRADE_VERIFY(a.isNormalized()); +} + void DualComplexTest::complexConjugated() { DualComplex a({-1.0f, 2.5f}, {3.0f, -7.5f}); DualComplex b({-1.0f, -2.5f}, {3.0f, 7.5f}); diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 7d8884026..372eaf572 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -70,10 +70,13 @@ struct DualQuaternionTest: Corrade::TestSuite::Tester { void convert(); void isNormalized(); + template void isNormalizedEpsilonRotation(); + template void isNormalizedEpsilonTranslation(); void lengthSquared(); void length(); void normalized(); + template void normalizedIterative(); void quaternionConjugated(); void dualConjugated(); @@ -115,12 +118,20 @@ DualQuaternionTest::DualQuaternionTest() { &DualQuaternionTest::convert, &DualQuaternionTest::isNormalized, + &DualQuaternionTest::isNormalizedEpsilonRotation, + &DualQuaternionTest::isNormalizedEpsilonRotation, + &DualQuaternionTest::isNormalizedEpsilonTranslation, + &DualQuaternionTest::isNormalizedEpsilonTranslation, &DualQuaternionTest::lengthSquared, &DualQuaternionTest::length, - &DualQuaternionTest::normalized, + &DualQuaternionTest::normalized}); - &DualQuaternionTest::quaternionConjugated, + addRepeatedTests({ + &DualQuaternionTest::normalizedIterative, + &DualQuaternionTest::normalizedIterative}, 1000); + + addTests({&DualQuaternionTest::quaternionConjugated, &DualQuaternionTest::dualConjugated, &DualQuaternionTest::conjugated, &DualQuaternionTest::inverted, @@ -150,6 +161,8 @@ void DualQuaternionTest::construct() { constexpr DualQuaternion d({{1.0f, 2.0f, 3.0f}, -4.0f}); CORRADE_COMPARE(d, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualQuaternionTest::constructVectorScalar() { @@ -161,6 +174,8 @@ void DualQuaternionTest::constructVectorScalar() { constexpr Quaternion c = a.dual(); CORRADE_COMPARE(c, Quaternion({0.5f, -3.1f, 3.3f}, 2.0f)); + + CORRADE_VERIFY((std::is_nothrow_constructible, Math::Dual>::value)); } void DualQuaternionTest::constructIdentity() { @@ -170,17 +185,29 @@ void DualQuaternionTest::constructIdentity() { CORRADE_COMPARE(b, DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); CORRADE_COMPARE(a.length(), 1.0f); CORRADE_COMPARE(b.length(), 1.0f); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualQuaternionTest::constructZero() { constexpr DualQuaternion a{ZeroInit}; CORRADE_COMPARE(a, DualQuaternion({{0.0f, 0.0f, 0.0f}, 0.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualQuaternionTest::constructNoInit() { DualQuaternion a{{{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f}}; new(&a) DualQuaternion{NoInit}; - CORRADE_COMPARE(a, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualQuaternionTest::constructFromVector() { @@ -189,6 +216,8 @@ void DualQuaternionTest::constructFromVector() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualQuaternionTest::constructConversion() { @@ -201,6 +230,8 @@ void DualQuaternionTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualQuaternionTest::constructCopy() { @@ -210,6 +241,9 @@ void DualQuaternionTest::constructCopy() { #endif DualQuaternion b(a); CORRADE_COMPARE(b, DualQuaternion({{1.0f, 2.0f, -3.0f}, -3.5f}, {{4.5f, -7.0f, 2.0f}, 1.0f})); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void DualQuaternionTest::convert() { @@ -242,7 +276,25 @@ void DualQuaternionTest::convert() { void DualQuaternionTest::isNormalized() { CORRADE_VERIFY(!DualQuaternion({{1.0f, 2.0f, 3.0f}, 4.0f}, {}).isNormalized()); - CORRADE_VERIFY((DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({3.0f, 1.0f, -0.5f})).isNormalized()); + CORRADE_VERIFY((DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({0.9f, -1.0f, -0.5f})).isNormalized()); +} + +template void DualQuaternionTest::isNormalizedEpsilonRotation() { + setTestCaseName(std::string{"isNormalizedEpsilonRotation<"} + TypeTraits::name() + ">"); + + CORRADE_VERIFY((Math::DualQuaternion{{{T(0.199367934417197) + TypeTraits::epsilon()/T(2.0), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); + CORRADE_VERIFY(!(Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083) + TypeTraits::epsilon()*T(2.0)}, {{T(0.440966117079373), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); +} + +template void DualQuaternionTest::isNormalizedEpsilonTranslation() { + setTestCaseName(std::string{"isNormalizedEpsilonTranslation<"} + TypeTraits::name() + ">"); + + CORRADE_VERIFY((Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373), T(-0.440120368706115) + TypeTraits::epsilon()*T(2.0), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); + CORRADE_VERIFY(!(Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373) + TypeTraits::epsilon()*T(4.0), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); + + /* Large translation -- large epsilon */ + CORRADE_VERIFY((Math::DualQuaternion{{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128)}, {{T(5056871.9114386), T(-245303.943266211) + TypeTraits::epsilon()*T(10000000.0), T(-606492.066475555)}, T(-6315.26116124973)}}.isNormalized())); + CORRADE_VERIFY(!(Math::DualQuaternion{{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128)}, {{T(5056871.9114386), T(-245303.943266211) + TypeTraits::epsilon()*T(20000000.0), T(-606492.066475555)}, T(-6315.26116124973)}}.isNormalized())); } void DualQuaternionTest::lengthSquared() { @@ -262,6 +314,29 @@ void DualQuaternionTest::normalized() { CORRADE_COMPARE(a.normalized(), b); } +namespace { + template struct NormalizedIterativeData; + template<> struct NormalizedIterativeData { + static Math::Vector3 translation() { return {10000.0f, -50.0f, 20000.0f}; } + }; + template<> struct NormalizedIterativeData { + static Math::Vector3 translation() { return {10000000000000.0, -500.0, 20000000000000.0}; } + }; +} + +template void DualQuaternionTest::normalizedIterative() { + setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits::name() + ">"); + + const auto axis = Math::Vector3{T(0.5), T(7.9), T(0.1)}.normalized(); + auto a = Math::DualQuaternion::rotation(Math::Deg{T(36.7)}, Math::Vector3{T(0.25), T(7.3), T(-1.1)}.normalized())*Math::DualQuaternion::translation(NormalizedIterativeData::translation()); + for(std::size_t i = 0; i != testCaseRepeatId(); ++i) { + a = Math::DualQuaternion::rotation(Math::Deg{T(87.1)}, axis)*a; + a = a.normalized(); + } + + CORRADE_VERIFY(a.isNormalized()); +} + void DualQuaternionTest::quaternionConjugated() { DualQuaternion a({{ 1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f, 3.3f}, 2.0f}); DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{-0.5f, 3.1f, -3.3f}, 2.0f}); diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index c99cebcbf..d7cd29c4c 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -27,6 +27,7 @@ #include #include "Magnum/Math/Dual.h" +#include "Magnum/Math/Quaternion.h" #include "Magnum/Math/Vector2.h" namespace Magnum { namespace Math { namespace Test { @@ -36,6 +37,7 @@ struct DualTest: Corrade::TestSuite::Tester { void construct(); void constructDefault(); + void constructZero(); void constructNoInit(); void constructConversion(); void constructCopy(); @@ -72,6 +74,7 @@ using namespace Literals; DualTest::DualTest() { addTests({&DualTest::construct, &DualTest::constructDefault, + &DualTest::constructZero, &DualTest::constructNoInit, &DualTest::constructConversion, &DualTest::constructCopy, @@ -106,17 +109,44 @@ void DualTest::construct() { constexpr Dual d(3.0f); CORRADE_COMPARE(d.real(), 3.0f); CORRADE_COMPARE(d.dual(), 0.0f); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualTest::constructDefault() { constexpr Dual a; + constexpr Math::Dual> b; + CORRADE_COMPARE(a, Dual(0.0f, 0.0f)); + CORRADE_COMPARE(b, Math::Dual>({{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 1.0f})); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); +} + +void DualTest::constructZero() { + constexpr Dual a{ZeroInit}; + constexpr Math::Dual> b{ZeroInit}; CORRADE_COMPARE(a, Dual(0.0f, 0.0f)); + CORRADE_COMPARE(b, Math::Dual>({{0.0f, 0.0f, 0.0f}, 0.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible>, ZeroInitT>::value)); } void DualTest::constructNoInit() { Dual a{2.0f, -7.5f}; + Math::Dual> b{{{3.0f, 0.1f, 1.0f}, 1.0f}, {{0.1f, 0.0f, 1.0f}, 0.3f}}; new(&a) Dual{NoInit}; - CORRADE_COMPARE(a, Dual(2.0f, -7.5f)); + new(&b) Math::Dual>{NoInit}; + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Dual(2.0f, -7.5f)); + CORRADE_COMPARE(b, (Math::Dual>{{{3.0f, 0.1f, 1.0f}, 1.0f}, {{0.1f, 0.0f, 1.0f}, 0.3f}})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible>, NoInitT>::value)); } void DualTest::constructConversion() { @@ -129,12 +159,17 @@ void DualTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void DualTest::constructCopy() { constexpr Dual a(2.0f, 3.0f); constexpr Dual b(a); CORRADE_COMPARE(b, Dual(2.0f, 3.0f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void DualTest::compare() { diff --git a/src/Magnum/Math/Test/FunctionsTest.cpp b/src/Magnum/Math/Test/FunctionsTest.cpp index 836aa9703..12ed46427 100644 --- a/src/Magnum/Math/Test/FunctionsTest.cpp +++ b/src/Magnum/Math/Test/FunctionsTest.cpp @@ -277,10 +277,10 @@ void FunctionsTest::normalizeUnsigned() { CORRADE_COMPARE((Math::normalize(0)), 0.0f); CORRADE_COMPARE((Math::normalize(255)), 1.0f); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE((Math::normalize(0)), 0.0); CORRADE_COMPARE((Math::normalize(std::numeric_limits::max())), 1.0); + #ifndef MAGNUM_TARGET_WEBGL CORRADE_COMPARE((Math::normalize(0)), 0.0); CORRADE_COMPARE((Math::normalize(std::numeric_limits::max())), 1.0); #endif @@ -303,11 +303,11 @@ void FunctionsTest::normalizeSigned() { CORRADE_COMPARE((Math::normalize(0)), 0.0f); CORRADE_COMPARE((Math::normalize(std::numeric_limits::max())), 1.0f); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE((Math::normalize(std::numeric_limits::min())), -1.0); CORRADE_COMPARE((Math::normalize(0)), 0.0); CORRADE_COMPARE((Math::normalize(std::numeric_limits::max())), 1.0); + #ifndef MAGNUM_TARGET_WEBGL CORRADE_COMPARE((Math::normalize(std::numeric_limits::min())), -1.0); CORRADE_COMPARE((Math::normalize(0)), 0.0); CORRADE_COMPARE((Math::normalize(std::numeric_limits::max())), 1.0); @@ -326,10 +326,10 @@ void FunctionsTest::denormalizeUnsigned() { CORRADE_COMPARE(Math::denormalize(0.0f), 0); CORRADE_COMPARE(Math::denormalize(1.0f), std::numeric_limits::max()); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(Math::denormalize(0.0), 0); CORRADE_COMPARE(Math::denormalize(1.0), std::numeric_limits::max()); + #ifndef MAGNUM_TARGET_WEBGL CORRADE_COMPARE(Math::denormalize(0.0l), 0); { #ifdef CORRADE_MSVC2015_COMPATIBILITY @@ -387,10 +387,10 @@ void FunctionsTest::renormalizeUnsinged() { CORRADE_COMPARE(Math::normalize(Math::denormalize(0.0f)), 0.0f); CORRADE_COMPARE(Math::normalize(Math::denormalize(1.0f)), 1.0f); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(Math::normalize(Math::denormalize(0.0)), 0.0); CORRADE_COMPARE(Math::normalize(Math::denormalize(1.0)), 1.0); + #ifndef MAGNUM_TARGET_WEBGL CORRADE_COMPARE(Math::normalize(Math::denormalize(0.0l)), 0.0l); { #ifdef CORRADE_MSVC2015_COMPATIBILITY @@ -410,11 +410,11 @@ void FunctionsTest::renormalizeSinged() { CORRADE_COMPARE(Math::normalize(Math::denormalize(0.0f)), 0.0f); CORRADE_COMPARE(Math::normalize(Math::denormalize(1.0f)), 1.0f); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(Math::normalize(Math::denormalize(-1.0)), -1.0); CORRADE_COMPARE(Math::normalize(Math::denormalize(0.0)), 0.0); CORRADE_COMPARE(Math::normalize(Math::denormalize(1.0)), 1.0); + #ifndef MAGNUM_TARGET_WEBGL CORRADE_COMPARE(Math::normalize(Math::denormalize(-1.0l)), -1.0l); CORRADE_COMPARE(Math::normalize(Math::denormalize(0.0l)), 0.0l); { diff --git a/src/Magnum/Math/Test/Matrix3Test.cpp b/src/Magnum/Math/Test/Matrix3Test.cpp index be6d680e0..25758233e 100644 --- a/src/Magnum/Math/Test/Matrix3Test.cpp +++ b/src/Magnum/Math/Test/Matrix3Test.cpp @@ -136,6 +136,8 @@ void Matrix3Test::construct() { CORRADE_COMPARE(a, Matrix3({3.0f, 5.0f, 8.0f}, {4.5f, 4.0f, 7.0f}, {7.9f, -1.0f, 8.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix3Test::constructIdentity() { @@ -154,6 +156,9 @@ void Matrix3Test::constructIdentity() { CORRADE_COMPARE(identity, identityExpected); CORRADE_COMPARE(identity2, identityExpected); CORRADE_COMPARE(identity3, identity3Expected); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix3Test::constructZero() { @@ -161,6 +166,8 @@ void Matrix3Test::constructZero() { CORRADE_COMPARE(a, Matrix3({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix3Test::constructNoInit() { @@ -168,9 +175,16 @@ void Matrix3Test::constructNoInit() { {4.5f, 4.0f, 7.0f}, {7.9f, -1.0f, 8.0f}}; new(&a) Matrix3{NoInit}; - CORRADE_COMPARE(a, Matrix3({3.0f, 5.0f, 8.0f}, - {4.5f, 4.0f, 7.0f}, - {7.9f, -1.0f, 8.0f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Matrix3({3.0f, 5.0f, 8.0f}, + {4.5f, 4.0f, 7.0f}, + {7.9f, -1.0f, 8.0f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix3Test::constructConversion() { @@ -184,6 +198,8 @@ void Matrix3Test::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix3Test::constructCopy() { @@ -197,6 +213,9 @@ void Matrix3Test::constructCopy() { CORRADE_COMPARE(b, Matrix3({3.0f, 5.0f, 8.0f}, {4.5f, 4.0f, 7.0f}, {7.9f, -1.0f, 8.0f})); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void Matrix3Test::convert() { diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index 3969e4817..cb62fc792 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include "Magnum/Math/Matrix4.h" @@ -84,7 +85,9 @@ struct Matrix4Test: Corrade::TestSuite::Tester { void shearingYZ(); void orthographicProjection(); void perspectiveProjection(); + void perspectiveProjectionInfiniteFar(); void perspectiveProjectionFov(); + void perspectiveProjectionFovInfiniteFar(); void lookAt(); void fromParts(); @@ -95,6 +98,7 @@ struct Matrix4Test: Corrade::TestSuite::Tester { void vectorParts(); void invertedRigid(); void transform(); + void transformProjection(); void debug(); void configuration(); @@ -106,6 +110,7 @@ typedef Math::Matrix4 Matrix4; typedef Math::Matrix4 Matrix4i; typedef Math::Matrix<3, Float> Matrix3x3; typedef Math::Vector3 Vector3; +typedef Math::Vector4 Vector4; typedef Math::Constants Constants; Matrix4Test::Matrix4Test() { @@ -132,7 +137,9 @@ Matrix4Test::Matrix4Test() { &Matrix4Test::shearingYZ, &Matrix4Test::orthographicProjection, &Matrix4Test::perspectiveProjection, + &Matrix4Test::perspectiveProjectionInfiniteFar, &Matrix4Test::perspectiveProjectionFov, + &Matrix4Test::perspectiveProjectionFovInfiniteFar, &Matrix4Test::lookAt, &Matrix4Test::fromParts, @@ -143,6 +150,7 @@ Matrix4Test::Matrix4Test() { &Matrix4Test::vectorParts, &Matrix4Test::invertedRigid, &Matrix4Test::transform, + &Matrix4Test::transformProjection, &Matrix4Test::debug, &Matrix4Test::configuration}); @@ -157,6 +165,8 @@ void Matrix4Test::construct() { {4.5f, 4.0f, 7.0f, 2.0f}, {1.0f, 2.0f, 3.0f, -1.0f}, {7.9f, -1.0f, 8.0f, -1.5f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix4Test::constructIdentity() { @@ -177,6 +187,9 @@ void Matrix4Test::constructIdentity() { CORRADE_COMPARE(identity, identityExpected); CORRADE_COMPARE(identity2, identityExpected); CORRADE_COMPARE(identity3, identity3Expected); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix4Test::constructZero() { @@ -185,6 +198,8 @@ void Matrix4Test::constructZero() { {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix4Test::constructNoInit() { @@ -193,10 +208,17 @@ void Matrix4Test::constructNoInit() { {1.0f, 2.0f, 3.0f, -1.0f}, {7.9f, -1.0f, 8.0f, -1.5f}}; new(&a) Matrix4{NoInit}; - CORRADE_COMPARE(a, Matrix4({3.0f, 5.0f, 8.0f, -3.0f}, - {4.5f, 4.0f, 7.0f, 2.0f}, - {1.0f, 2.0f, 3.0f, -1.0f}, - {7.9f, -1.0f, 8.0f, -1.5f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Matrix4({3.0f, 5.0f, 8.0f, -3.0f}, + {4.5f, 4.0f, 7.0f, 2.0f}, + {1.0f, 2.0f, 3.0f, -1.0f}, + {7.9f, -1.0f, 8.0f, -1.5f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix4Test::constructConversion() { @@ -212,6 +234,8 @@ void Matrix4Test::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Matrix4Test::constructCopy() { @@ -227,6 +251,9 @@ void Matrix4Test::constructCopy() { {4.5f, 4.0f, 7.0f, 2.0f}, {1.0f, 2.0f, 3.0f, -1.0f}, {7.9f, -1.0f, 8.0f, -1.5f})); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void Matrix4Test::convert() { @@ -382,7 +409,12 @@ void Matrix4Test::orthographicProjection() { {0.0f, 0.5f, 0.0f, 0.0f}, {0.0f, 0.0f, -0.25f, 0.0f}, {0.0f, 0.0f, -1.25f, 1.0f}); - CORRADE_COMPARE(Matrix4::orthographicProjection({5.0f, 4.0f}, 1, 9), expected); + Matrix4 actual = Matrix4::orthographicProjection({5.0f, 4.0f}, 1.0f, 9.0f); + CORRADE_COMPARE(actual, expected); + + /* NDC is left-handed, so point on near plane should be -1, far +1 */ + CORRADE_COMPARE(actual.transformPoint({0.0f, 0.0f, -1.0f}), Vector3(0.0f, 0.0f, -1.0f)); + CORRADE_COMPARE(actual.transformPoint({0.0f, 0.0f, -9.0f}), Vector3(0.0f, 0.0f, +1.0f)); } void Matrix4Test::perspectiveProjection() { @@ -390,7 +422,26 @@ void Matrix4Test::perspectiveProjection() { {0.0f, 7.111111f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.9411764f, -1.0f}, {0.0f, 0.0f, -94.1176452f, 0.0f}); - CORRADE_COMPARE(Matrix4::perspectiveProjection({16.0f, 9.0f}, 32.0f, 100), expected); + Matrix4 actual = Matrix4::perspectiveProjection({16.0f, 9.0f}, 32.0f, 100.0f); + CORRADE_COMPARE(actual, expected); + + /* NDC is left-handed, so point on near plane should be -1, far +1 */ + CORRADE_COMPARE(actual.transformPoint({0.0f, 0.0f, -32.0f}), Vector3(0.0f, 0.0f, -1.0f)); + CORRADE_COMPARE(actual.transformPoint({0.0f, 0.0f, -100.0f}), Vector3(0.0f, 0.0f, +1.0f)); +} + +void Matrix4Test::perspectiveProjectionInfiniteFar() { + Matrix4 expected({4.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 7.111111f, 0.0f, 0.0f}, + {0.0f, 0.0f, -1.0f, -1.0f}, + {0.0f, 0.0f, -64.0f, 0.0f}); + Matrix4 actual = Matrix4::perspectiveProjection({16.0f, 9.0f}, 32.0f, Constants::inf()); + CORRADE_COMPARE(actual, expected); + + /* NDC is left-handed, so point on near plane should be -1 and a *vector* + in direction of far plane +1 */ + CORRADE_COMPARE(actual.transformPoint({0.0f, 0.0f, -32.0f}), Vector3(0.0f, 0.0f, -1.0f)); + CORRADE_COMPARE(actual.transformVector({0.0f, 0.0f, -1.0f}), Vector3(0.0f, 0.0f, +1.0f)); } void Matrix4Test::perspectiveProjectionFov() { @@ -398,7 +449,15 @@ void Matrix4Test::perspectiveProjectionFov() { { 0.0f, 9.788454f, 0.0f, 0.0f}, { 0.0f, 0.0f, -1.9411764f, -1.0f}, { 0.0f, 0.0f, -94.1176452f, 0.0f}); - CORRADE_COMPARE(Matrix4::perspectiveProjection(Deg(27.0f), 2.35f, 32.0f, 100), expected); + CORRADE_COMPARE(Matrix4::perspectiveProjection(Deg(27.0f), 2.35f, 32.0f, 100.0f), expected); +} + +void Matrix4Test::perspectiveProjectionFovInfiniteFar() { + Matrix4 expected({4.1652994f, 0.0f, 0.0f, 0.0f}, + { 0.0f, 9.788454f, 0.0f, 0.0f}, + { 0.0f, 0.0f, -1.0f, -1.0f}, + { 0.0f, 0.0f, -64.0f, 0.0f}); + CORRADE_COMPARE(Matrix4::perspectiveProjection(Deg(27.0f), 2.35f, 32.0f, Constants::inf()), expected); } void Matrix4Test::fromParts() { @@ -546,42 +605,35 @@ void Matrix4Test::transform() { CORRADE_COMPARE(a.transformPoint(v), Vector3(3.0f, -4.0f, 9.0f)); } +void Matrix4Test::transformProjection() { + Matrix4 a = Matrix4::perspectiveProjection({2.0f, 2.0f}, 1.0f, 100.0f); + Vector3 v{0.0f, 0.0f, -100.0f}; + + CORRADE_COMPARE(a.transformPoint(v), Vector3(0.0f, 0.0f, 1.0f)); +} + void Matrix4Test::lookAt() { - Matrix4 a = Matrix4::lookAt({0.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f}, - {0.0f, 0.0f, 1.0f}); + Vector3 translation{5.3f, -8.9f, -10.0f}; + Vector3 target{19.0f, 29.3f, 0.0f}; + Matrix4 a = Matrix4::lookAt(translation, target, Vector3::xAxis()); + + /* It's just a translation and rotation */ CORRADE_VERIFY(a.isRigidTransformation()); - CORRADE_COMPARE(a, Matrix4({1.0f, 0.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 1.0f, 0.0f}, - {0.0f, -1.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 0.0f, 1.0f})); - Matrix4 b = Matrix4::lookAt({100.0f, 200.0f, 300.0f}, - { 0.0f, 0.0f, 0.0f}, - { 0.0f, 1.0f, 0.0f}); - CORRADE_VERIFY(b.isRigidTransformation()); - CORRADE_COMPARE(b, Matrix4({ 0.948683f, 0.0f, -0.316228f, 0.0f}, - {-0.169031f, 0.845154f, -0.507093f, 0.0f}, - { 0.267261f, 0.534522f, 0.801784f, 0.0f}, - { 100.0f, 200.0f, 300.0f, 1.0f})); - - Matrix4 c = Matrix4::lookAt({3.0f, 0.0f, 0.0f}, - {0.0f, 4.0f, 5.0f}, - {0.0f, 0.0f, 1.0f}); - CORRADE_VERIFY(c.isRigidTransformation()); - CORRADE_COMPARE(c, Matrix4({ 0.8f, 0.6f, 0.0f, 0.0f}, - {0.424264f, -0.565685f, 0.707107f, 0.0f}, - {0.424264f, -0.565685f, -0.707107f, 0.0f}, - { 3.0f, 0.0f, 0.0f, 1.0f})); - - Matrix4 d = Matrix4::lookAt({ 0.0f, 3.0f, 0.0f}, - {-5.0f, 0.0f, -4.0f}, - { 0.0f, 1.0f, 0.0f}); - CORRADE_VERIFY(d.isRigidTransformation()); - CORRADE_COMPARE(d, Matrix4({ 0.624695f, 0.0f, -0.780869f, 0.0f}, - {-0.331295f, 0.905539f, -0.265036f, 0.0f}, - { 0.707107f, 0.424264f, 0.565685f, 0.0f}, - { 0.0f, 3.0f, 0.0f, 1.0f})); + /* The matrix should translate to the position */ + CORRADE_COMPARE(a.translation(), translation); + + /* Forward vector should point in direction of the target */ + CORRADE_COMPARE(dot(-a.backward(), (target - translation).normalized()), 1.0f); + + /* Up vector should be in the same direction as X axis */ + CORRADE_COMPARE_AS(dot(Vector3::xAxis(), a.up()), 0.0f, Corrade::TestSuite::Compare::Greater); + + /* Just to be sure */ + CORRADE_COMPARE(a, Matrix4({ 0.0f, 0.253247f, -0.967402f, 0.0f}, + {0.944754f, -0.317095f, -0.0830092f, 0.0f}, + {-0.32778f, -0.913957f, -0.239256f, 0.0f}, + { 5.3f, -8.9f, -10.0f, 1.0f})); } void Matrix4Test::debug() { diff --git a/src/Magnum/Math/Test/MatrixTest.cpp b/src/Magnum/Math/Test/MatrixTest.cpp index 7a216e220..974bebe35 100644 --- a/src/Magnum/Math/Test/MatrixTest.cpp +++ b/src/Magnum/Math/Test/MatrixTest.cpp @@ -123,6 +123,8 @@ void MatrixTest::construct() { Vector4(4.5f, 4.0f, 7.0f, 2.0f), Vector4(1.0f, 2.0f, 3.0f, -1.0f), Vector4(7.9f, -1.0f, 8.0f, -1.5f))); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void MatrixTest::constructIdentity() { @@ -143,6 +145,9 @@ void MatrixTest::constructIdentity() { CORRADE_COMPARE(identity, identityExpected); CORRADE_COMPARE(identity2, identityExpected); CORRADE_COMPARE(identity3, identity3Expected); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void MatrixTest::constructZero() { @@ -151,6 +156,8 @@ void MatrixTest::constructZero() { Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 0.0f))); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void MatrixTest::constructNoInit() { @@ -159,10 +166,17 @@ void MatrixTest::constructNoInit() { Vector4(1.0f, 2.0f, 3.0f, -1.0f), Vector4(7.9f, -1.0f, 8.0f, -1.5f)}; new(&a) Matrix4x4{NoInit}; - CORRADE_COMPARE(a, Matrix4x4(Vector4(3.0f, 5.0f, 8.0f, -3.0f), - Vector4(4.5f, 4.0f, 7.0f, 2.0f), - Vector4(1.0f, 2.0f, 3.0f, -1.0f), - Vector4(7.9f, -1.0f, 8.0f, -1.5f))); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Matrix4x4(Vector4(3.0f, 5.0f, 8.0f, -3.0f), + Vector4(4.5f, 4.0f, 7.0f, 2.0f), + Vector4(1.0f, 2.0f, 3.0f, -1.0f), + Vector4(7.9f, -1.0f, 8.0f, -1.5f))); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void MatrixTest::constructConversion() { @@ -178,6 +192,8 @@ void MatrixTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void MatrixTest::constructCopy() { @@ -193,6 +209,9 @@ void MatrixTest::constructCopy() { Vector4(4.5f, 4.0f, 7.0f, 2.0f), Vector4(1.0f, 2.0f, 3.0f, -1.0f), Vector4(7.9f, -1.0f, 8.0f, -1.5f))); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void MatrixTest::convert() { diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index 4addf3c40..2c2f5caf2 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -25,6 +25,7 @@ #include #include +#include #include "Magnum/Math/Matrix4.h" #include "Magnum/Math/Quaternion.h" @@ -68,6 +69,7 @@ struct QuaternionTest: Corrade::TestSuite::Tester { void compare(); void isNormalized(); + template void isNormalizedEpsilon(); void addSubtract(); void negated(); @@ -78,6 +80,7 @@ struct QuaternionTest: Corrade::TestSuite::Tester { void dotSelf(); void length(); void normalized(); + template void normalizedIterative(); void conjugated(); void inverted(); @@ -114,6 +117,8 @@ QuaternionTest::QuaternionTest() { &QuaternionTest::compare, &QuaternionTest::isNormalized, + &QuaternionTest::isNormalizedEpsilon, + &QuaternionTest::isNormalizedEpsilon, &QuaternionTest::addSubtract, &QuaternionTest::negated, @@ -123,9 +128,13 @@ QuaternionTest::QuaternionTest() { &QuaternionTest::dot, &QuaternionTest::dotSelf, &QuaternionTest::length, - &QuaternionTest::normalized, + &QuaternionTest::normalized}); - &QuaternionTest::conjugated, + addRepeatedTests({ + &QuaternionTest::normalizedIterative, + &QuaternionTest::normalizedIterative}, 1000); + + addTests({&QuaternionTest::conjugated, &QuaternionTest::inverted, &QuaternionTest::invertedNormalized, @@ -148,6 +157,8 @@ void QuaternionTest::construct() { constexpr Float c = a.scalar(); CORRADE_COMPARE(b, Vector3(1.0f, 2.0f, 3.0f)); CORRADE_COMPARE(c, -4.0f); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void QuaternionTest::constructIdentity() { @@ -157,17 +168,29 @@ void QuaternionTest::constructIdentity() { CORRADE_COMPARE(b, Quaternion({0.0f, 0.0f, 0.0f}, 1.0f)); CORRADE_COMPARE(a.length(), 1.0f); CORRADE_COMPARE(b.length(), 1.0f); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void QuaternionTest::constructZero() { constexpr Quaternion a{ZeroInit}; CORRADE_COMPARE(a, Quaternion({0.0f, 0.0f, 0.0f}, 0.0f)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void QuaternionTest::constructNoInit() { Quaternion a{{1.0f, 2.0f, 3.0f}, -4.0f}; new(&a) Quaternion{NoInit}; - CORRADE_COMPARE(a, Quaternion({1.0f, 2.0f, 3.0f}, -4.0f)); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Quaternion({1.0f, 2.0f, 3.0f}, -4.0f)); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void QuaternionTest::constructFromVector() { @@ -176,6 +199,8 @@ void QuaternionTest::constructFromVector() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void QuaternionTest::constructConversion() { @@ -188,12 +213,17 @@ void QuaternionTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void QuaternionTest::constructCopy() { constexpr Quaternion a({1.0f, -3.0f, 7.0f}, 2.5f); constexpr Quaternion b(a); CORRADE_COMPARE(b, Quaternion({1.0f, -3.0f, 7.0f}, 2.5f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void QuaternionTest::convert() { @@ -232,6 +262,13 @@ void QuaternionTest::isNormalized() { CORRADE_VERIFY(Quaternion::rotation(Deg(23.0f), Vector3::xAxis()).isNormalized()); } +template void QuaternionTest::isNormalizedEpsilon() { + setTestCaseName(std::string{"isNormalizedEpsilon<"} + TypeTraits::name() + ">"); + + CORRADE_VERIFY((Math::Quaternion{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128) + TypeTraits::epsilon()/T(2.0)}.isNormalized())); + CORRADE_VERIFY(!(Math::Quaternion{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128) + TypeTraits::epsilon()*T(2.0)}.isNormalized())); +} + void QuaternionTest::addSubtract() { Quaternion a({ 1.0f, 3.0f, -2.0f}, -4.0f); Quaternion b({-0.5f, 1.4f, 3.0f}, 12.0f); @@ -282,6 +319,19 @@ void QuaternionTest::normalized() { CORRADE_COMPARE(normalized, Quaternion({1.0f, 3.0f, -2.0f}, -4.0f)/std::sqrt(30.0f)); } +template void QuaternionTest::normalizedIterative() { + setTestCaseName(std::string{"normalizedIterative<"} + TypeTraits::name() + ">"); + + const auto axis = Math::Vector3{T(0.5), T(7.9), T(0.1)}.normalized(); + auto a = Math::Quaternion::rotation(Math::Deg{T(36.7)}, Math::Vector3{T(0.25), T(7.3), T(-1.1)}.normalized()); + for(std::size_t i = 0; i != testCaseRepeatId(); ++i) { + a = Math::Quaternion::rotation(Math::Deg{T(87.1)}, axis)*a; + a = a.normalized(); + } + + CORRADE_VERIFY(a.isNormalized()); +} + void QuaternionTest::conjugated() { CORRADE_COMPARE(Quaternion({ 1.0f, 3.0f, -2.0f}, -4.0f).conjugated(), Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f)); @@ -372,33 +422,47 @@ void QuaternionTest::matrix() { CORRADE_COMPARE(o.str(), "Math::Quaternion::fromMatrix(): the matrix is not orthogonal\n"); /* Trace > 0 */ - CORRADE_VERIFY(m.trace() > 0.0f); + CORRADE_COMPARE_AS(m.trace(), 0.0f, Corrade::TestSuite::Compare::Greater); CORRADE_COMPARE(Quaternion::fromMatrix(m), q); /* Trace < 0, max is diagonal[2] */ Matrix3x3 m2 = Matrix4::rotation(Deg(130.0f), axis).rotationScaling(); Quaternion q2 = Quaternion::rotation(Deg(130.0f), axis); - CORRADE_VERIFY(m2.trace() < 0.0f); - CORRADE_VERIFY(m2.diagonal()[2] > std::max(m2.diagonal()[0], m2.diagonal()[1])); + CORRADE_COMPARE_AS(m2.trace(), 0.0f, Corrade::TestSuite::Compare::Less); + CORRADE_COMPARE_AS(m2.diagonal()[2], + std::max(m2.diagonal()[0], m2.diagonal()[1]), + Corrade::TestSuite::Compare::Greater); CORRADE_COMPARE(Quaternion::fromMatrix(m2), q2); /* Trace < 0, max is diagonal[1] */ Vector3 axis2 = Vector3(-3.0f, 5.0f, 1.0f).normalized(); Matrix3x3 m3 = Matrix4::rotation(Deg(130.0f), axis2).rotationScaling(); Quaternion q3 = Quaternion::rotation(Deg(130.0f), axis2); - CORRADE_VERIFY(m3.trace() < 0.0f); - CORRADE_VERIFY(m3.diagonal()[1] > std::max(m3.diagonal()[0], m3.diagonal()[2])); + CORRADE_COMPARE_AS(m3.trace(), 0.0f, Corrade::TestSuite::Compare::Less); + CORRADE_COMPARE_AS(m3.diagonal()[1], + std::max(m3.diagonal()[0], m3.diagonal()[2]), + Corrade::TestSuite::Compare::Greater); CORRADE_COMPARE(Quaternion::fromMatrix(m3), q3); /* Trace < 0, max is diagonal[0] */ Vector3 axis3 = Vector3(5.0f, -3.0f, 1.0f).normalized(); Matrix3x3 m4 = Matrix4::rotation(Deg(130.0f), axis3).rotationScaling(); Quaternion q4 = Quaternion::rotation(Deg(130.0f), axis3); - CORRADE_VERIFY(m4.trace() < 0.0f); - CORRADE_VERIFY(m4.diagonal()[0] > std::max(m4.diagonal()[1], m4.diagonal()[2])); + CORRADE_COMPARE_AS(m4.trace(), 0.0f, Corrade::TestSuite::Compare::Less); + CORRADE_COMPARE_AS(m4.diagonal()[0], + std::max(m4.diagonal()[1], m4.diagonal()[2]), + Corrade::TestSuite::Compare::Greater); CORRADE_COMPARE(Quaternion::fromMatrix(m4), q4); } +/* The crappy 4.9 20140827 (prerelease) in Android NDK segfaults when + optimizing the following function. Dialing down the optimization helps. No + problem when calling Math::lerp() anywhere else, so I won't dig further. + Fuck this. */ +#if defined(CORRADE_TARGET_ANDROID) && __GNUC__*100 + __GNUC_MINOR__*10 + __GNUC_PATCHLEVEL__ == 490 +#pragma GCC push_options +#pragma GCC optimize("O0") +#endif void QuaternionTest::lerp() { Quaternion a = Quaternion::rotation(Deg(15.0f), Vector3(1.0f/Constants::sqrt3())); Quaternion b = Quaternion::rotation(Deg(23.0f), Vector3::xAxis()); @@ -416,6 +480,9 @@ void QuaternionTest::lerp() { Quaternion lerp = Math::lerp(a, b, 0.35f); CORRADE_COMPARE(lerp, Quaternion({0.119127f, 0.049134f, 0.049134f}, 0.990445f)); } +#if defined(CORRADE_TARGET_ANDROID) && __GNUC__*100 + __GNUC_MINOR__*10 + __GNUC_PATCHLEVEL__ == 490 +#pragma GCC pop_options +#endif void QuaternionTest::slerp() { Quaternion a = Quaternion::rotation(Deg(15.0f), Vector3(1.0f/Constants::sqrt3())); diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index a428f77d9..ad869b6e2 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -178,6 +178,10 @@ void RangeTest::construct() { CORRADE_COMPARE(a, (Range<1, Int>(3, 23))); CORRADE_COMPARE(b, (Range<2, Int>({3, 5}, {23, 78}))); CORRADE_COMPARE(c, (Range<3, Int>({3, 5, -7}, {23, 78, 2}))); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RangeTest::constructDefault() { @@ -194,6 +198,13 @@ void RangeTest::constructDefault() { CORRADE_COMPARE(b2, Range2Di({0, 0}, {0, 0})); CORRADE_COMPARE(c1, Range3Di({0, 0, 0}, {0, 0, 0})); CORRADE_COMPARE(c2, Range3Di({0, 0, 0}, {0, 0, 0})); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RangeTest::constructNoInit() { @@ -205,9 +216,18 @@ void RangeTest::constructNoInit() { new(&b) Range2Di{NoInit}; new(&c) Range3Di{NoInit}; - CORRADE_COMPARE(a, (Range1Di{3, 23})); - CORRADE_COMPARE(b, (Range2Di{{3, 5}, {23, 78}})); - CORRADE_COMPARE(c, (Range3Di{{3, 5, -7}, {23, 78, 2}})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, (Range1Di{3, 23})); + CORRADE_COMPARE(b, (Range2Di{{3, 5}, {23, 78}})); + CORRADE_COMPARE(c, (Range3Di{{3, 5, -7}, {23, 78, 2}})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RangeTest::constructFromSize() { @@ -235,6 +255,10 @@ void RangeTest::constructConversion() { CORRADE_VERIFY(!(std::is_convertible::value)); CORRADE_VERIFY(!(std::is_convertible::value)); CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RangeTest::constructCopy() { @@ -249,6 +273,13 @@ void RangeTest::constructCopy() { CORRADE_COMPARE(d, Range1Di(3, 23)); CORRADE_COMPARE(e, Range2Di({3, 5}, {23, 78})); CORRADE_COMPARE(f, Range3Di({3, 5, -7}, {23, 78, 2})); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void RangeTest::convert() { diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index 36a496df4..c26676375 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -81,6 +81,8 @@ struct RectangularMatrixTest: Corrade::TestSuite::Tester { void multiplyVector(); void transposed(); + void flippedCols(); + void flippedRows(); void diagonal(); void vector(); @@ -128,6 +130,8 @@ RectangularMatrixTest::RectangularMatrixTest() { &RectangularMatrixTest::multiplyVector, &RectangularMatrixTest::transposed, + &RectangularMatrixTest::flippedCols, + &RectangularMatrixTest::flippedRows, &RectangularMatrixTest::diagonal, &RectangularMatrixTest::vector, @@ -146,6 +150,8 @@ void RectangularMatrixTest::construct() { CORRADE_COMPARE(a, Matrix3x4(Vector4(1.0f, 2.0f, 3.0f, 4.0f), Vector4(5.0f, 6.0f, 7.0f, 8.0f), Vector4(9.0f, 10.0f, 11.0f, 12.0f))); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RectangularMatrixTest::constructDefault() { @@ -159,6 +165,9 @@ void RectangularMatrixTest::constructDefault() { Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f))); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RectangularMatrixTest::constructNoInit() { @@ -166,9 +175,16 @@ void RectangularMatrixTest::constructNoInit() { Vector4(5.0f, 6.0f, 7.0f, 8.0f), Vector4(9.0f, 10.0f, 11.0f, 12.0f)}; new(&a) Matrix3x4{NoInit}; - CORRADE_COMPARE(a, Matrix3x4(Vector4(1.0f, 2.0f, 3.0f, 4.0f), - Vector4(5.0f, 6.0f, 7.0f, 8.0f), - Vector4(9.0f, 10.0f, 11.0f, 12.0f))); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Matrix3x4(Vector4(1.0f, 2.0f, 3.0f, 4.0f), + Vector4(5.0f, 6.0f, 7.0f, 8.0f), + Vector4(9.0f, 10.0f, 11.0f, 12.0f))); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RectangularMatrixTest::constructConversion() { @@ -181,6 +197,8 @@ void RectangularMatrixTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void RectangularMatrixTest::constructFromData() { @@ -222,6 +240,9 @@ void RectangularMatrixTest::constructCopy() { CORRADE_COMPARE(b, Matrix3x4(Vector4(1.0f, 2.0f, 3.0f, 4.0f), Vector4(5.0f, 6.0f, 7.0f, 8.0f), Vector4(9.0f, 10.0f, 11.0f, 12.0f))); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void RectangularMatrixTest::convert() { @@ -284,11 +305,16 @@ void RectangularMatrixTest::data() { } void RectangularMatrixTest::row() { - const Matrix3x4 a(Vector4(1.0f, 2.0f, 3.0f, 4.0f), - Vector4(5.0f, 6.0f, 7.0f, 8.0f), - Vector4(9.0f, 10.0f, 11.0f, 12.0f)); + Matrix3x4 a(Vector4(1.0f, 2.0f, 3.0f, 4.0f), + Vector4(5.0f, 6.0f, 7.0f, 8.0f), + Vector4(9.0f, 10.0f, 11.0f, 12.0f)); CORRADE_COMPARE(a.row(1), Vector3(2.0f, 6.0f, 10.0f)); + + a.setRow(1, {-2.1f, -6.1f, -10.1f}); + CORRADE_COMPARE(a, (Matrix3x4{Vector4{1.0f, -2.1f, 3.0f, 4.0f}, + Vector4{5.0f, -6.1f, 7.0f, 8.0f}, + Vector4{9.0f, -10.1f, 11.0f, 12.0f}})); } void RectangularMatrixTest::compare() { @@ -409,6 +435,36 @@ void RectangularMatrixTest::transposed() { CORRADE_COMPARE(original.transposed(), transposed); } +void RectangularMatrixTest::flippedCols() { + constexpr Matrix4x3 original{Vector3{ 0.0f, 1.0f, 3.0f}, + Vector3{ 4.0f, 5.0f, 7.0f}, + Vector3{ 8.0f, 9.0f, 11.0f}, + Vector3{12.0f, 13.0f, 15.0f}}; + constexpr Matrix4x3 flipped = original.flippedCols(); + + Matrix4x3 expectedFlipped{Vector3{12.0f, 13.0f, 15.0f}, + Vector3{ 8.0f, 9.0f, 11.0f}, + Vector3{ 4.0f, 5.0f, 7.0f}, + Vector3{ 0.0f, 1.0f, 3.0f}}; + + CORRADE_COMPARE(flipped, expectedFlipped); +} + +void RectangularMatrixTest::flippedRows() { + constexpr Matrix4x3 original{Vector3{ 0.0f, 1.0f, 3.0f}, + Vector3{ 4.0f, 5.0f, 7.0f}, + Vector3{ 8.0f, 9.0f, 11.0f}, + Vector3{12.0f, 13.0f, 15.0f}}; + constexpr Matrix4x3 flipped = original.flippedRows(); + + Matrix4x3 expectedFlipped{Vector3{ 3.0f, 1.0f, 0.0f}, + Vector3{ 7.0f, 5.0f, 4.0f}, + Vector3{11.0f, 9.0f, 8.0f}, + Vector3{15.0f, 13.0f, 12.0f}}; + + CORRADE_COMPARE(flipped, expectedFlipped); +} + void RectangularMatrixTest::diagonal() { Vector3 diagonal(-1.0f, 5.0f, 11.0f); @@ -500,6 +556,10 @@ void RectangularMatrixTest::subclassTypes() { CORRADE_VERIFY((std::is_same>::value)); CORRADE_VERIFY((std::is_same>::value)); CORRADE_VERIFY((std::is_same()), BasicMat<3, Float>>::value)); + + /* Functions */ + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); } void RectangularMatrixTest::subclass() { @@ -560,6 +620,22 @@ void RectangularMatrixTest::subclass() { const Math::Vector<1, Float> i(2.0f); const Math::RectangularMatrix<1, 1, Float> j(3.0f); CORRADE_COMPARE(i*j, (BasicMat<1, Float>(6.0f))); + + /* Functions */ + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Probably because copy is not constexpr */ + constexpr + #endif + Mat2x2 flippedCols = Mat2x2{Vector2{-1.0f, 5.0f}, + Vector2{ 7.0f, -2.0f}}.flippedCols(); + CORRADE_COMPARE(flippedCols, (Mat2x2{Vector2{ 7.0f, -2.0f}, + Vector2{-1.0f, 5.0f}})); + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Probably because copy is not constexpr */ + constexpr + #endif + Mat2x2 flippedRows = Mat2x2{Vector2{-1.0f, 5.0f}, + Vector2{ 7.0f, -2.0f}}.flippedRows(); + CORRADE_COMPARE(flippedRows, (Mat2x2{Vector2{ 5.0f, -1.0f}, + Vector2{-2.0f, 7.0f}})); } void RectangularMatrixTest::debug() { diff --git a/src/Magnum/Math/Test/TypeTraitsTest.cpp b/src/Magnum/Math/Test/TypeTraitsTest.cpp index 7f733e6ed..1ee4f0c21 100644 --- a/src/Magnum/Math/Test/TypeTraitsTest.cpp +++ b/src/Magnum/Math/Test/TypeTraitsTest.cpp @@ -24,6 +24,9 @@ */ #include +#ifdef _MSC_VER +#include /* std::max() */ +#endif #include "Magnum/Math/TypeTraits.h" #include "Magnum/Math/Constants.h" @@ -33,75 +36,220 @@ namespace Magnum { namespace Math { namespace Test { struct TypeTraitsTest: Corrade::TestSuite::Tester { explicit TypeTraitsTest(); + void sizeOfLongDouble(); + void name(); + template void equalsIntegral(); template void equalsFloatingPoint0(); template void equalsFloatingPoint1(); template void equalsFloatingPointLarge(); template void equalsFloatingPointInfinity(); template void equalsFloatingPointNaN(); + + template void equalsZeroIntegral(); + template void equalsZeroFloatingPoint(); + template void equalsZeroFloatingPointSmall(); + template void equalsZeroFloatingPointLarge(); +}; + +namespace { + +enum: std::size_t { EqualsZeroDataCount = 3 }; + +struct { + const char* name; + Float a, aStep; + Double b, bStep; + long double c, cStep; + + Float get(Float) const { return a; } + Float getStep(Float) const { return aStep; } + Double get(Double) const { return b; } + Double getStep(Double) const { return bStep; } + long double get(long double) const { return c; } + long double getStep(long double) const { return cStep; } +} EqualsZeroData[EqualsZeroDataCount] = { + {"", -3.141592653589793f, 5.0e-5f, -3.141592653589793, 5.0e-14, -3.141592653589793l, + #if !defined(_MSC_VER) && !defined(CORRADE_TARGET_ANDROID) + 5.0e-17l + #else + 5.0e-14 + #endif + }, + {"small", 1.0e-6f, 5.0e-6f, -1.0e-15, 5.0e-15, 1.0e-18l, + #if !defined(_MSC_VER) && !defined(CORRADE_TARGET_ANDROID) + 5.0e-18l + #else + 5.0e-15 + #endif + }, + {"large", 12345.0f, 0.2f, 12345678901234.0, 0.2, + #if !defined(_MSC_VER) && !defined(CORRADE_TARGET_ANDROID) + -12345678901234567.0l, + #else + -12345678901234.0l, + #endif + 0.2l}, }; +} + TypeTraitsTest::TypeTraitsTest() { - addTests({&TypeTraitsTest::equalsIntegral, + addTests({&TypeTraitsTest::sizeOfLongDouble, + &TypeTraitsTest::name, + + &TypeTraitsTest::equalsIntegral, &TypeTraitsTest::equalsIntegral, &TypeTraitsTest::equalsIntegral, &TypeTraitsTest::equalsIntegral, &TypeTraitsTest::equalsIntegral, &TypeTraitsTest::equalsIntegral, + #ifndef CORRADE_TARGET_EMSCRIPTEN &TypeTraitsTest::equalsIntegral, &TypeTraitsTest::equalsIntegral, + #endif + &TypeTraitsTest::equalsFloatingPoint0, - #ifndef MAGNUM_TARGET_GLES &TypeTraitsTest::equalsFloatingPoint0, + #ifndef CORRADE_TARGET_EMSCRIPTEN + &TypeTraitsTest::equalsFloatingPoint0, #endif &TypeTraitsTest::equalsFloatingPoint1, - #ifndef MAGNUM_TARGET_GLES &TypeTraitsTest::equalsFloatingPoint1, + #ifndef CORRADE_TARGET_EMSCRIPTEN + &TypeTraitsTest::equalsFloatingPoint1, #endif &TypeTraitsTest::equalsFloatingPointLarge, - #ifndef MAGNUM_TARGET_GLES &TypeTraitsTest::equalsFloatingPointLarge, + #ifndef CORRADE_TARGET_EMSCRIPTEN + &TypeTraitsTest::equalsFloatingPointLarge, #endif &TypeTraitsTest::equalsFloatingPointInfinity, - #ifndef MAGNUM_TARGET_GLES &TypeTraitsTest::equalsFloatingPointInfinity, - #endif &TypeTraitsTest::equalsFloatingPointNaN, - #ifndef MAGNUM_TARGET_GLES - &TypeTraitsTest::equalsFloatingPointNaN + &TypeTraitsTest::equalsFloatingPointNaN, + + &TypeTraitsTest::equalsZeroIntegral, + &TypeTraitsTest::equalsZeroIntegral, + &TypeTraitsTest::equalsZeroIntegral, + &TypeTraitsTest::equalsZeroIntegral, + &TypeTraitsTest::equalsZeroIntegral, + &TypeTraitsTest::equalsZeroIntegral, + #ifndef CORRADE_TARGET_EMSCRIPTEN + &TypeTraitsTest::equalsZeroIntegral, + &TypeTraitsTest::equalsZeroIntegral, #endif }); + + addInstancedTests({ + &TypeTraitsTest::equalsZeroFloatingPoint, + &TypeTraitsTest::equalsZeroFloatingPoint, + #ifndef CORRADE_TARGET_EMSCRIPTEN + &TypeTraitsTest::equalsZeroFloatingPoint + #endif + }, EqualsZeroDataCount); +} + +void TypeTraitsTest::sizeOfLongDouble() { + #ifdef CORRADE_TARGET_EMSCRIPTEN + CORRADE_SKIP("Not defined in Emscripten."); + #else + #if defined(_MSC_VER) || defined(CORRADE_TARGET_ANDROID) + CORRADE_COMPARE(sizeof(long double), 8); + CORRADE_EXPECT_FAIL("long double is equivalent to double on MSVC and Android."); + #endif + + /* It's 80 bit, but has to be aligned somehow, so 128 bits / 16 bytes */ + CORRADE_COMPARE(sizeof(long double), 16); + #endif +} + +void TypeTraitsTest::name() { + CORRADE_COMPARE(TypeTraits::name(), std::string{"UnsignedShort"}); + CORRADE_COMPARE(TypeTraits::name(), std::string{"Float"}); } template void TypeTraitsTest::equalsIntegral() { + setTestCaseName(std::string{"equalsIntegral<"} + TypeTraits::name() + ">"); + + CORRADE_VERIFY(TypeTraits::equals(1, 1)); + CORRADE_VERIFY(!TypeTraits::equals(1, -1)); CORRADE_VERIFY(!TypeTraits::equals(1, 1+TypeTraits::epsilon())); } template void TypeTraitsTest::equalsFloatingPoint0() { + setTestCaseName(std::string{"equalsFloatingPoint0<"} + TypeTraits::name() + ">"); + CORRADE_VERIFY(TypeTraits::equals(T(0)+TypeTraits::epsilon()/T(2), T(0))); CORRADE_VERIFY(!TypeTraits::equals(T(0)+TypeTraits::epsilon()*T(2), T(0))); } template void TypeTraitsTest::equalsFloatingPoint1() { + setTestCaseName(std::string{"equalsFloatingPoint1<"} + TypeTraits::name() + ">"); + CORRADE_VERIFY(TypeTraits::equals(T(1)+TypeTraits::epsilon()/T(2), T(1))); CORRADE_VERIFY(!TypeTraits::equals(T(1)+TypeTraits::epsilon()*T(3), T(1))); } template void TypeTraitsTest::equalsFloatingPointLarge() { + setTestCaseName(std::string{"equalsFloatingPointLarge<"} + TypeTraits::name() + ">"); + CORRADE_VERIFY(TypeTraits::equals(T(25)+TypeTraits::epsilon()*T(2), T(25))); CORRADE_VERIFY(!TypeTraits::equals(T(25)+TypeTraits::epsilon()*T(75), T(25))); } template void TypeTraitsTest::equalsFloatingPointInfinity() { + setTestCaseName(std::string{"equalsFloatingPointInfinity<"} + TypeTraits::name() + ">"); + CORRADE_VERIFY(TypeTraits::equals(Constants::inf(), Constants::inf())); } template void TypeTraitsTest::equalsFloatingPointNaN() { + setTestCaseName(std::string{"equalsFloatingPointNaN<"} + TypeTraits::name() + ">"); + CORRADE_VERIFY(!TypeTraits::equals(Constants::nan(), Constants::nan())); } +namespace { + /* Argh! Why there is no standard std::abs() for unsigned types? */ + template::value>::type> T abs(T value) { + return value; + } + template::value>::type> T abs(T value) { + return std::abs(value); + } +} + +template void TypeTraitsTest::equalsZeroIntegral() { + setTestCaseName(std::string{"equalsZeroIntegral<"} + TypeTraits::name() + ">"); + + const T a(-123); + const T b(-123); + const T magnitude = std::max(abs(a), abs(b)); + + CORRADE_VERIFY(TypeTraits::equals(a, b)); + CORRADE_VERIFY(TypeTraits::equalsZero(a - b, magnitude)); + CORRADE_VERIFY(!TypeTraits::equalsZero(a - b + TypeTraits::epsilon(), magnitude)); +} + +template void TypeTraitsTest::equalsZeroFloatingPoint() { + setTestCaseName(std::string{"equalsZeroFloatingPoint<"} + TypeTraits::name() + ">"); + setTestCaseDescription(EqualsZeroData[testCaseInstanceId()].name); + + const T a = EqualsZeroData[testCaseInstanceId()].get(T{}); + const T b = EqualsZeroData[testCaseInstanceId()].get(T{}); + const T step = EqualsZeroData[testCaseInstanceId()].getStep(T{}); + const T magnitude = std::max(abs(a), abs(b)); + + CORRADE_VERIFY(TypeTraits::equals(a + step/T(2.0), b)); + CORRADE_VERIFY(TypeTraits::equalsZero(a + step/T(2.0) - b, magnitude)); + + CORRADE_VERIFY(!TypeTraits::equals(a - step*T(2.0), b)); + CORRADE_VERIFY(!TypeTraits::equalsZero(a - step*T(2.0) - b, magnitude)); +} + }}} CORRADE_TEST_MAIN(Magnum::Math::Test::TypeTraitsTest) diff --git a/src/Magnum/Math/Test/UnitTest.cpp b/src/Magnum/Math/Test/UnitTest.cpp index 256497e90..4cb58e33a 100644 --- a/src/Magnum/Math/Test/UnitTest.cpp +++ b/src/Magnum/Math/Test/UnitTest.cpp @@ -74,17 +74,31 @@ void UnitTest::construct() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void UnitTest::constructDefault() { - constexpr Sec b; + constexpr Sec a; + constexpr Sec b{ZeroInit}; + CORRADE_COMPARE(a, Sec(0.0f)); CORRADE_COMPARE(b, Sec(0.0f)); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void UnitTest::constructNoInit() { Sec a{25.0f}; new(&a) Sec{NoInit}; - CORRADE_COMPARE(a, Sec{25.0f}); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, Sec{25.0f}); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void UnitTest::constructConversion() { @@ -94,6 +108,8 @@ void UnitTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void UnitTest::compare() { diff --git a/src/Magnum/Math/Test/Vector2Test.cpp b/src/Magnum/Math/Test/Vector2Test.cpp index d066d8e21..774f584fd 100644 --- a/src/Magnum/Math/Test/Vector2Test.cpp +++ b/src/Magnum/Math/Test/Vector2Test.cpp @@ -104,6 +104,8 @@ Vector2Test::Vector2Test() { void Vector2Test::construct() { constexpr Vector2 a = {1.5f, 2.5f}; CORRADE_COMPARE(a, (Vector<2, Float>(1.5f, 2.5f))); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector2Test::constructDefault() { @@ -111,12 +113,22 @@ void Vector2Test::constructDefault() { constexpr Vector2 b{ZeroInit}; CORRADE_COMPARE(a, Vector2(0.0f, 0.0f)); CORRADE_COMPARE(b, Vector2(0.0f, 0.0f)); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector2Test::constructNoInit() { Vector2 a{1.5f, 2.5f}; new(&a) Vector2{NoInit}; - CORRADE_COMPARE(a, (Vector2{1.5f, 2.5f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, (Vector2{1.5f, 2.5f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector2Test::constructOneValue() { @@ -125,6 +137,8 @@ void Vector2Test::constructOneValue() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector2Test::constructConversion() { @@ -134,6 +148,8 @@ void Vector2Test::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector2Test::constructCopy() { @@ -143,6 +159,9 @@ void Vector2Test::constructCopy() { #endif Vector2 b(a); CORRADE_COMPARE(b, Vector2(1.5f, 2.5f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void Vector2Test::convert() { diff --git a/src/Magnum/Math/Test/Vector3Test.cpp b/src/Magnum/Math/Test/Vector3Test.cpp index 8d53b8f79..044f87ef8 100644 --- a/src/Magnum/Math/Test/Vector3Test.cpp +++ b/src/Magnum/Math/Test/Vector3Test.cpp @@ -102,6 +102,8 @@ Vector3Test::Vector3Test() { void Vector3Test::construct() { constexpr Vector3 a = {1.0f, 2.5f, -3.0f}; CORRADE_COMPARE(a, (Vector<3, Float>(1.0f, 2.5f, -3.0f))); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector3Test::constructDefault() { @@ -109,12 +111,22 @@ void Vector3Test::constructDefault() { constexpr Vector3 b{ZeroInit}; CORRADE_COMPARE(a, Vector3(0.0f, 0.0f, 0.0f)); CORRADE_COMPARE(b, Vector3(0.0f, 0.0f, 0.0f)); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector3Test::constructNoInit() { Vector3 a{1.0f, 2.5f, -3.0f}; new(&a) Vector3{NoInit}; - CORRADE_COMPARE(a, (Vector3{1.0f, 2.5f, -3.0f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, (Vector3{1.0f, 2.5f, -3.0f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector3Test::constructOneValue() { @@ -123,12 +135,16 @@ void Vector3Test::constructOneValue() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector3Test::constructParts() { constexpr Vector2 a(1.0f, 2.0f); constexpr Vector3 b = {a, 3.0f}; CORRADE_COMPARE(b, Vector3(1.0f, 2.0f, 3.0f)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector3Test::constructConversion() { @@ -138,6 +154,8 @@ void Vector3Test::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector3Test::constructCopy() { @@ -147,6 +165,9 @@ void Vector3Test::constructCopy() { #endif Vector3 b(a); CORRADE_COMPARE(b, Vector3(1.0f, 2.5f, -3.0f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void Vector3Test::convert() { diff --git a/src/Magnum/Math/Test/Vector4Test.cpp b/src/Magnum/Math/Test/Vector4Test.cpp index 5eff2562a..e89ee1382 100644 --- a/src/Magnum/Math/Test/Vector4Test.cpp +++ b/src/Magnum/Math/Test/Vector4Test.cpp @@ -101,6 +101,8 @@ Vector4Test::Vector4Test() { void Vector4Test::construct() { constexpr Vector4 a = {1.0f, -2.5f, 3.0f, 4.1f}; CORRADE_COMPARE(a, (Vector<4, Float>(1.0f, -2.5f, 3.0f, 4.1f))); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector4Test::constructPad() { @@ -124,12 +126,22 @@ void Vector4Test::constructDefault() { constexpr Vector4 b{ZeroInit}; CORRADE_COMPARE(a, Vector4(0.0f, 0.0f, 0.0f, 0.0f)); CORRADE_COMPARE(b, Vector4(0.0f, 0.0f, 0.0f, 0.0f)); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector4Test::constructNoInit() { Vector4 a{1.0f, -2.5f, 3.0f, 4.1f}; new(&a) Vector4{NoInit}; - CORRADE_COMPARE(a, (Vector4{1.0f, -2.5f, 3.0f, 4.1f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, (Vector4{1.0f, -2.5f, 3.0f, 4.1f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector4Test::constructOneValue() { @@ -138,12 +150,16 @@ void Vector4Test::constructOneValue() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector4Test::constructParts() { constexpr Vector3 a(1.0f, 2.0f, 3.0f); constexpr Vector4 b = {a, 4.0f}; CORRADE_COMPARE(b, Vector4(1.0f, 2.0f, 3.0f, 4.0f)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector4Test::constructConversion() { @@ -153,6 +169,8 @@ void Vector4Test::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void Vector4Test::constructCopy() { @@ -162,6 +180,9 @@ void Vector4Test::constructCopy() { #endif Vector4 b(a); CORRADE_COMPARE(b, Vector4(1.0f, -2.5f, 3.0f, 4.1f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void Vector4Test::convert() { diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index 64c6ec747..5204a0b2e 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -100,6 +100,8 @@ struct VectorTest: Corrade::TestSuite::Tester { void projected(); void projectedOntoNormalized(); + void flipped(); + void angle(); void subclassTypes(); @@ -158,6 +160,8 @@ VectorTest::VectorTest() { &VectorTest::projected, &VectorTest::projectedOntoNormalized, + &VectorTest::flipped, + &VectorTest::angle, &VectorTest::subclassTypes, @@ -170,6 +174,8 @@ VectorTest::VectorTest() { void VectorTest::construct() { constexpr Vector4 a = {1.0f, 2.0f, -3.0f, 4.5f}; CORRADE_COMPARE(a, Vector4(1.0f, 2.0f, -3.0f, 4.5f)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void VectorTest::constructFromData() { @@ -194,12 +200,22 @@ void VectorTest::constructDefault() { constexpr Vector4 b{ZeroInit}; CORRADE_COMPARE(a, Vector4(0.0f, 0.0f, 0.0f, 0.0f)); CORRADE_COMPARE(b, Vector4(0.0f, 0.0f, 0.0f, 0.0f)); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void VectorTest::constructNoInit() { Vector4 a{1.0f, 2.0f, -3.0f, 4.5f}; new(&a) Vector4{NoInit}; - CORRADE_COMPARE(a, (Vector4{1.0f, 2.0f, -3.0f, 4.5f})); + { + #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ + CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); + #endif + CORRADE_COMPARE(a, (Vector4{1.0f, 2.0f, -3.0f, 4.5f})); + } + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void VectorTest::constructOneValue() { @@ -209,6 +225,8 @@ void VectorTest::constructOneValue() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void VectorTest::constructOneComponent() { @@ -217,6 +235,8 @@ void VectorTest::constructOneComponent() { /* Implicit constructor must work */ constexpr Vector1 vec = 1.0f; CORRADE_COMPARE(vec, Vector1(1)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void VectorTest::constructConversion() { @@ -227,12 +247,17 @@ void VectorTest::constructConversion() { /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); } void VectorTest::constructCopy() { constexpr Vector4 a(1.0f, 3.5f, 4.0f, -2.7f); constexpr Vector4 b(a); CORRADE_COMPARE(b, Vector4(1.0f, 3.5f, 4.0f, -2.7f)); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void VectorTest::convert() { @@ -462,6 +487,12 @@ void VectorTest::projectedOntoNormalized() { CORRADE_COMPARE(projected, vector.projected(line)); } +void VectorTest::flipped() { + constexpr Vector4 vector{1.0f, -3.5f, 2.1f, 0.5f}; + constexpr Vector4 flipped = vector.flipped(); + CORRADE_COMPARE(flipped, (Vector4{0.5f, 2.1f, -3.5f, 1.0f})); +} + void VectorTest::angle() { std::ostringstream o; Error redirectError{&o}; @@ -557,6 +588,7 @@ void VectorTest::subclassTypes() { CORRADE_VERIFY((std::is_same::value)); CORRADE_VERIFY((std::is_same::value)); CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); } void VectorTest::subclass() { @@ -615,17 +647,34 @@ void VectorTest::subclass() { /* Integral multiplication/division */ CORRADE_COMPARE(Vec2i(2, 4)*1.5f, Vec2i(3, 6)); CORRADE_COMPARE(1.5f*Vec2i(2, 4), Vec2i(3, 6)); - CORRADE_COMPARE(Vec2i(2, 4)/(2.0f/3.0f), Vec2i(3, 6)); + { + #ifdef CORRADE_TARGET_EMSCRIPTEN + CORRADE_EXPECT_FAIL_IF(Vec2i(2, 4)/(2.0f/3.0f) == Vec2i(2, 5), + "Emscripten -O1 misoptimizes the following (-O2 works)."); + #endif + CORRADE_COMPARE(Vec2i(2, 4)/(2.0f/3.0f), Vec2i(3, 6)); + } CORRADE_COMPARE(Vec2i(2, 4)*Vec2(-1.5f, 0.5f), Vec2i(-3, 2)); CORRADE_COMPARE(Vec2(-1.5f, 0.5f)*Vec2i(2, 4), Vec2i(-3, 2)); - CORRADE_COMPARE(Vec2i(2, 4)/Vec2(-2.0f/3.0f, 2.0f), Vec2i(-3, 2)); + { + #ifdef CORRADE_TARGET_EMSCRIPTEN + CORRADE_EXPECT_FAIL_IF(Vec2i(2, 4)/Vec2(-2.0f/3.0f, 2.0f) == Vec2i(-2, 2), + "Emscripten -O1 misoptimizes the following (-O2 works)."); + #endif + CORRADE_COMPARE(Vec2i(2, 4)/Vec2(-2.0f/3.0f, 2.0f), Vec2i(-3, 2)); + } /* Functions */ CORRADE_COMPARE(Vec2(3.0f, 0.0f).normalized(), Vec2(1.0f, 0.0f)); CORRADE_COMPARE(Vec2(3.0f, 0.0f).resized(6.0f), Vec2(6.0f, 0.0f)); CORRADE_COMPARE(Vec2(1.0f, 1.0f).projected({0.0f, 2.0f}), Vec2(0.0f, 1.0f)); CORRADE_COMPARE(Vec2(1.0f, 1.0f).projectedOntoNormalized({0.0f, 1.0f}), Vec2(0.0f, 1.0f)); + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Probably because copy is not constexpr */ + constexpr + #endif + Vec2 flipped = Vec2{1.0f, 0.4f}.flipped(); + CORRADE_COMPARE(flipped, (Vec2{0.4f, 1.0f})); } void VectorTest::debug() { diff --git a/src/Magnum/Math/TypeTraits.h b/src/Magnum/Math/TypeTraits.h index 7a081dc94..13d47bbde 100644 --- a/src/Magnum/Math/TypeTraits.h +++ b/src/Magnum/Math/TypeTraits.h @@ -33,22 +33,43 @@ #include "Magnum/Types.h" -/** @brief Precision when testing floats for equality */ +/** +@brief Precision when testing floats for equality + +They have "at least" 6 significant digits of precision, taking one digit less +for more headroom. +*/ #ifndef FLOAT_EQUALITY_PRECISION #define FLOAT_EQUALITY_PRECISION 1.0e-5f #endif -/** @brief Precision when testing doubles for equality */ +/** +@brief Precision when testing doubles for equality + +They have "at least" 15 significant digits of precision, taking one digit less +for more headroom. +*/ #ifndef DOUBLE_EQUALITY_PRECISION -#define DOUBLE_EQUALITY_PRECISION 1.0e-12 +#define DOUBLE_EQUALITY_PRECISION 1.0e-14 #endif /** @brief Precision when testing long doubles for equality -@todo some proper value please + +They have "at least" 18 significant digits of precision, taking one digit less +for more headroom. + +@attention On MSVC the precision is the same as for doubles, because they are + internally the same type (source: https://msdn.microsoft.com/en-us/library/9cx8xs15.aspx). + The same is apparently for @ref CORRADE_TARGET_ANDROID "Android", but I + couldn't find any source for that. */ #ifndef LONG_DOUBLE_EQUALITY_PRECISION -#define LONG_DOUBLE_EQUALITY_PRECISION 1.0e-18l +#if !defined(_MSC_VER) && !defined(CORRADE_TARGET_ANDROID) +#define LONG_DOUBLE_EQUALITY_PRECISION 1.0e-17l +#else +#define LONG_DOUBLE_EQUALITY_PRECISION 1.0e-14l +#endif #endif namespace Magnum { namespace Math { @@ -60,6 +81,10 @@ namespace Implementation { constexpr static bool equals(T a, T b) { return a == b; } + + constexpr static bool equalsZero(T a, T) { + return !a; + } }; } @@ -87,6 +112,14 @@ template struct TypeTraits: Implementation::TypeTraitsDefault { */ typedef U FloatingPointType; + /** + * @brief Type name + * + * Returns a string representation of type name, such as `"UnsignedInt"` + * for @ref Magnum::UnsignedInt "UnsignedInt". + */ + constexpr static const char* name(); + /** * @brief Epsilon value for fuzzy compare * @@ -103,12 +136,49 @@ template struct TypeTraits: Implementation::TypeTraitsDefault { * value), pure equality comparison everywhere else. */ static bool equals(T a, T b); + + /** + * @brief Fuzzy compare to zero with magnitude + * + * Uses fuzzy compare for floating-point types (using @ref epsilon() + * value), pure equality comparison everywhere else. Use this function when + * comparing e.g. a calculated nearly-zero difference with zero, knowing + * the magnitude of original values so the epsilon can be properly scaled. + * In other words, the following lines are equivalent: + * @code + * Float a, b; + * Math::TypeTraits::equals(a, b); + * Math::TypeTraits::equalsZero(a - b, Math::max(Math::abs(a), Math::abs(b))); + * @endcode + */ + static bool equalsZero(T a, T magnitude); #endif }; /* Integral scalar types */ namespace Implementation { - template struct TypeTraitsIntegral: TypeTraitsDefault { + template struct TypeTraitsName; + #ifndef DOXYGEN_GENERATING_OUTPUT + #define _c(type) template<> struct TypeTraitsName { \ + constexpr static const char* name() { return #type; } \ + }; + _c(UnsignedByte) + _c(Byte) + _c(UnsignedShort) + _c(Short) + _c(UnsignedInt) + _c(Int) + #ifndef MAGNUM_TARGET_WEBGL + _c(UnsignedLong) + _c(Long) + #endif + _c(Float) + _c(Double) + _c(long double) + #undef _c + #endif + + template struct TypeTraitsIntegral: TypeTraitsDefault, TypeTraitsName { constexpr static T epsilon() { return T(1); } }; } @@ -127,35 +197,28 @@ template<> struct TypeTraits: Implementation::TypeTraitsIntegral { typedef Float FloatingPointType; }; template<> struct TypeTraits: Implementation::TypeTraitsIntegral { - #ifndef MAGNUM_TARGET_GLES typedef Double FloatingPointType; - #endif }; template<> struct TypeTraits: Implementation::TypeTraitsIntegral { - #ifndef MAGNUM_TARGET_GLES typedef Double FloatingPointType; - #endif }; #ifndef MAGNUM_TARGET_WEBGL template<> struct TypeTraits: Implementation::TypeTraitsIntegral { - #ifndef MAGNUM_TARGET_GLES typedef long double FloatingPointType; - #endif }; template<> struct TypeTraits: Implementation::TypeTraitsIntegral { - #ifndef MAGNUM_TARGET_GLES typedef long double FloatingPointType; - #endif }; #endif /* Floating-point scalar types */ namespace Implementation { -template struct TypeTraitsFloatingPoint { +template struct TypeTraitsFloatingPoint: TypeTraitsName { TypeTraitsFloatingPoint() = delete; static bool equals(T a, T b); + static bool equalsZero(T a, T epsilon); }; /* Adapted from http://floating-point-gui.de/errors/comparison/ */ @@ -176,6 +239,20 @@ template bool TypeTraitsFloatingPoint::equals(const T a, const T b) return difference/(absA + absB) < TypeTraits::epsilon(); } +template bool TypeTraitsFloatingPoint::equalsZero(const T a, const T magnitude) { + /* Shortcut for binary equality */ + if(a == T(0.0)) return true; + + const T absA = std::abs(a); + + /* The value is extremely close to zero, relative error is meaningless */ + if(absA < TypeTraits::epsilon()) + return absA < TypeTraits::epsilon(); + + /* Relative error */ + return absA*T(0.5)/magnitude < TypeTraits::epsilon(); +} + } template<> struct TypeTraits: Implementation::TypeTraitsFloatingPoint { @@ -183,13 +260,11 @@ template<> struct TypeTraits: Implementation::TypeTraitsFloatingPoint struct TypeTraits: Implementation::TypeTraitsFloatingPoint { typedef Double FloatingPointType; constexpr static Double epsilon() { return DOUBLE_EQUALITY_PRECISION; } }; -#endif template<> struct TypeTraits: Implementation::TypeTraitsFloatingPoint { typedef long double FloatingPointType; diff --git a/src/Magnum/Math/Unit.h b/src/Magnum/Math/Unit.h index 840df7f47..571b98e22 100644 --- a/src/Magnum/Math/Unit.h +++ b/src/Magnum/Math/Unit.h @@ -47,16 +47,19 @@ template class Derived, class T> class Unit { typedef T Type; /**< @brief Underlying data type */ /** @brief Construct zero value */ - constexpr /*implicit*/ Unit(ZeroInitT = ZeroInit): _value(T(0)) {} + constexpr /*implicit*/ Unit(ZeroInitT = ZeroInit) noexcept: _value(T(0)) {} /** @brief Construct without initializing the contents */ - explicit Unit(NoInitT) {} + explicit Unit(NoInitT) noexcept {} /** @brief Explicit conversion from unitless type */ - constexpr explicit Unit(T value): _value(value) {} + constexpr explicit Unit(T value) noexcept: _value(value) {} /** @brief Construct from another underlying type */ - template constexpr explicit Unit(Unit value): _value(T(value._value)) {} + template constexpr explicit Unit(Unit value) noexcept: _value(T(value._value)) {} + + /** @brief Copy constructor */ + constexpr /*implicit*/ Unit(const Unit& other) noexcept = default; /** @brief Explicit conversion to underlying type */ constexpr explicit operator T() const { return _value; } diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 8d8fc5bcf..938e3c786 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -73,8 +73,10 @@ namespace Implementation { /** @relatesalso Vector @brief Dot product of two vectors -Returns `0` when two vectors are perpendicular, `1` when two *normalized* -vectors are parallel and `-1` when two *normalized* vectors are antiparallel. @f[ +Returns `0` when two vectors are perpendicular, `> 0` when two vectors are in +the same general direction, `1` when two *normalized* vectors are parallel, +`< 0` when two vectors are in opposite general direction and `-1` when two +*normalized* vectors are antiparallel. @f[ \boldsymbol a \cdot \boldsymbol b = \sum_{i=0}^{n-1} \boldsymbol a_i \boldsymbol b_i @f] @see @ref Vector::dot() const, @ref Vector::operator-(), @ref Vector2::perpendicular() @@ -173,10 +175,10 @@ template class Vector { * \boldsymbol v = \boldsymbol 0 * @f] */ - constexpr /*implicit*/ Vector(ZeroInitT = ZeroInit): _data{} {} + constexpr /*implicit*/ Vector(ZeroInitT = ZeroInit) noexcept: _data{} {} /** @brief Construct vector without initializing the contents */ - explicit Vector(NoInitT) {} + explicit Vector(NoInitT) noexcept {} /** @todo Creating Vector from combination of vector and scalar types */ @@ -186,16 +188,16 @@ template class Vector { * @param next Next values */ #ifdef DOXYGEN_GENERATING_OUTPUT - template constexpr /*implicit*/ Vector(T first, U... next); + template constexpr /*implicit*/ Vector(T first, U... next) noexcept; #else - template::type> constexpr /*implicit*/ Vector(T first, U... next): _data{first, next...} {} + template::type> constexpr /*implicit*/ Vector(T first, U... next) noexcept: _data{first, next...} {} #endif /** @brief Construct vector with one value for all fields */ #ifdef DOXYGEN_GENERATING_OUTPUT - constexpr explicit Vector(T value); + constexpr explicit Vector(T value) noexcept; #else - template::value && size != 1, T>::type> constexpr explicit Vector(U value): Vector(typename Implementation::GenerateSequence::Type(), value) {} + template::value && size != 1, T>::type> constexpr explicit Vector(U value) noexcept: Vector(typename Implementation::GenerateSequence::Type(), value) {} #endif /** @@ -209,16 +211,13 @@ template class Vector { * // integral == {1, 2, -15, 7} * @endcode */ - template constexpr explicit Vector(const Vector& other): Vector(typename Implementation::GenerateSequence::Type(), other) {} + template constexpr explicit Vector(const Vector& other) noexcept: Vector(typename Implementation::GenerateSequence::Type(), other) {} /** @brief Construct vector from external representation */ - template::from(std::declval()))> constexpr explicit Vector(const U& other): Vector(Implementation::VectorConverter::from(other)) {} + template::from(std::declval()))> constexpr explicit Vector(const U& other) noexcept: Vector(Implementation::VectorConverter::from(other)) {} /** @brief Copy constructor */ - constexpr Vector(const Vector&) = default; - - /** @brief Assignment operator */ - Vector& operator=(const Vector&) = default; + constexpr /*implicit*/ Vector(const Vector&) noexcept = default; /** @brief Convert vector to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { @@ -536,6 +535,17 @@ template class Vector { */ Vector projectedOntoNormalized(const Vector& line) const; + /** + * @brief Flipped vector + * + * Returns the vector with components in reverse order. + * @see @ref RectangularMatrix::flippedCols(), + * @ref RectangularMatrix::flippedRows() + */ + constexpr Vector flipped() const { + return flippedInternal(typename Implementation::GenerateReverseSequence::Type{}); + } + /** * @brief Sum of values in the vector * @@ -566,15 +576,19 @@ template class Vector { private: /* Implementation for Vector::Vector(const Vector&) */ - template constexpr explicit Vector(Implementation::Sequence, const Vector& vector): _data{T(vector._data[sequence])...} {} + template constexpr explicit Vector(Implementation::Sequence, const Vector& vector) noexcept: _data{T(vector._data[sequence])...} {} /* Implementation for Vector::Vector(U) */ - template constexpr explicit Vector(Implementation::Sequence, T value): _data{Implementation::repeat(value, sequence)...} {} + template constexpr explicit Vector(Implementation::Sequence, T value) noexcept: _data{Implementation::repeat(value, sequence)...} {} template constexpr static Vector padInternal(Implementation::Sequence, const Vector& a, T value) { return {sequence < otherSize ? a[sequence] : value...}; } + template constexpr Vector flippedInternal(Implementation::Sequence) const { + return {(*this)[sequence]...}; + } + T _data[size]; }; @@ -1085,12 +1099,10 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<2, UnsignedInt>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<3, UnsignedInt>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<4, UnsignedInt>&); -#ifndef MAGNUM_TARGET_GLES extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<2, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<3, Double>&); extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<4, Double>&); #endif -#endif #ifndef DOXYGEN_GENERATING_OUTPUT #define MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(size, Type) \ @@ -1104,11 +1116,6 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili return Math::Vector::pad(a, value); \ } \ \ - Type& operator=(const Type& other) { \ - Math::Vector::operator=(other); \ - return *this; \ - } \ - \ Type operator-() const { \ return Math::Vector::operator-(); \ } \ @@ -1166,6 +1173,9 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili } \ Type projectedOntoNormalized(const Math::Vector& other) const { \ return Math::Vector::projectedOntoNormalized(other); \ + } \ + constexpr Type flipped() const { \ + return Math::Vector::flipped(); \ } #define MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(size, Type) \ @@ -1356,7 +1366,7 @@ template inline T Vector::max() const { namespace Corrade { namespace Utility { -/** @configurationvalue{Magnum::Math::RectangularMatrix} */ +/** @configurationvalue{Magnum::Math::Vector} */ template struct ConfigurationValue> { ConfigurationValue() = delete; @@ -1404,12 +1414,10 @@ extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; extern template struct MAGNUM_EXPORT ConfigurationValue>; #endif -#endif }} diff --git a/src/Magnum/Math/Vector2.h b/src/Magnum/Math/Vector2.h index 9bd0809ff..1c6d68e2d 100644 --- a/src/Magnum/Math/Vector2.h +++ b/src/Magnum/Math/Vector2.h @@ -112,7 +112,7 @@ template class Vector2: public Vector<2, T> { #endif /** @copydoc Vector::Vector(ZeroInitT) */ - constexpr /*implicit*/ Vector2(ZeroInitT = ZeroInit) + constexpr /*implicit*/ Vector2(ZeroInitT = ZeroInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -121,7 +121,7 @@ template class Vector2: public Vector<2, T> { {} /** @copydoc Vector::Vector(NoInitT) */ - explicit Vector2(NoInitT) + explicit Vector2(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -130,7 +130,7 @@ template class Vector2: public Vector<2, T> { {} /** @copydoc Vector::Vector(T) */ - constexpr explicit Vector2(T value): Vector<2, T>(value) {} + constexpr explicit Vector2(T value) noexcept: Vector<2, T>(value) {} /** * @brief Constructor @@ -139,10 +139,10 @@ template class Vector2: public Vector<2, T> { * \boldsymbol v = \begin{pmatrix} x \\ y \end{pmatrix} * @f] */ - constexpr /*implicit*/ Vector2(T x, T y): Vector<2, T>(x, y) {} + constexpr /*implicit*/ Vector2(T x, T y) noexcept: Vector<2, T>(x, y) {} /** @copydoc Vector::Vector(const Vector&) */ - template constexpr explicit Vector2(const Vector<2, U>& other): Vector<2, T>(other) {} + template constexpr explicit Vector2(const Vector<2, U>& other) noexcept: Vector<2, T>(other) {} /** @brief Construct vector from external representation */ template class Vector2: public Vector<2, T> { constexpr explicit Vector2(const U& other): Vector<2, T>(Implementation::VectorConverter<2, T, U>::from(other)) {} /** @brief Copy constructor */ - constexpr Vector2(const Vector<2, T>& other): Vector<2, T>(other) {} + constexpr /*implicit*/ Vector2(const Vector<2, T>& other) noexcept: Vector<2, T>(other) {} T& x() { return (*this)[0]; } /**< @brief X component */ constexpr T x() const { return (*this)[0]; } /**< @overload */ diff --git a/src/Magnum/Math/Vector3.h b/src/Magnum/Math/Vector3.h index 4302c5322..0b14ea04e 100644 --- a/src/Magnum/Math/Vector3.h +++ b/src/Magnum/Math/Vector3.h @@ -134,7 +134,7 @@ template class Vector3: public Vector<3, T> { #endif /** @copydoc Vector::Vector(ZeroInitT) */ - constexpr /*implicit*/ Vector3(ZeroInitT = ZeroInit) + constexpr /*implicit*/ Vector3(ZeroInitT = ZeroInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -143,7 +143,7 @@ template class Vector3: public Vector<3, T> { {} /** @copydoc Vector::Vector(NoInitT) */ - explicit Vector3(NoInitT) + explicit Vector3(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -152,7 +152,7 @@ template class Vector3: public Vector<3, T> { {} /** @copydoc Vector::Vector(T) */ - constexpr explicit Vector3(T value): Vector<3, T>(value) {} + constexpr explicit Vector3(T value) noexcept: Vector<3, T>(value) {} /** * @brief Constructor @@ -161,7 +161,7 @@ template class Vector3: public Vector<3, T> { * \boldsymbol v = \begin{pmatrix} x \\ y \\ z \end{pmatrix} * @f] */ - constexpr /*implicit*/ Vector3(T x, T y, T z): Vector<3, T>(x, y, z) {} + constexpr /*implicit*/ Vector3(T x, T y, T z) noexcept: Vector<3, T>(x, y, z) {} /** * @brief Constructor @@ -170,10 +170,10 @@ template class Vector3: public Vector<3, T> { * \boldsymbol v = \begin{pmatrix} v_x \\ v_y \\ z \end{pmatrix} * @f] */ - constexpr /*implicit*/ Vector3(const Vector2& xy, T z): Vector<3, T>(xy[0], xy[1], z) {} + constexpr /*implicit*/ Vector3(const Vector2& xy, T z) noexcept: Vector<3, T>(xy[0], xy[1], z) {} /** @copydoc Vector::Vector(const Vector&) */ - template constexpr explicit Vector3(const Vector<3, U>& other): Vector<3, T>(other) {} + template constexpr explicit Vector3(const Vector<3, U>& other) noexcept: Vector<3, T>(other) {} /** @brief Construct vector from external representation */ template class Vector3: public Vector<3, T> { constexpr explicit Vector3(const U& other): Vector<3, T>(Implementation::VectorConverter<3, T, U>::from(other)) {} /** @brief Copy constructor */ - constexpr Vector3(const Vector<3, T>& other): Vector<3, T>(other) {} + constexpr /*implicit*/ Vector3(const Vector<3, T>& other) noexcept: Vector<3, T>(other) {} /** * @brief X component diff --git a/src/Magnum/Math/Vector4.h b/src/Magnum/Math/Vector4.h index baf4c7ee0..1323b3ee4 100644 --- a/src/Magnum/Math/Vector4.h +++ b/src/Magnum/Math/Vector4.h @@ -60,7 +60,7 @@ template class Vector4: public Vector<4, T> { } /** @copydoc Vector::Vector(ZeroInitT) */ - constexpr /*implicit*/ Vector4(ZeroInitT = ZeroInit) + constexpr /*implicit*/ Vector4(ZeroInitT = ZeroInit) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -69,7 +69,7 @@ template class Vector4: public Vector<4, T> { {} /** @copydoc Vector::Vector(NoInitT) */ - explicit Vector4(NoInitT) + explicit Vector4(NoInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT /* MSVC 2015 can't handle {} here */ @@ -78,7 +78,7 @@ template class Vector4: public Vector<4, T> { {} /** @copydoc Vector::Vector(T) */ - constexpr explicit Vector4(T value): Vector<4, T>(value) {} + constexpr explicit Vector4(T value) noexcept: Vector<4, T>(value) {} /** * @brief Constructor @@ -87,7 +87,7 @@ template class Vector4: public Vector<4, T> { * \boldsymbol v = \begin{pmatrix} x \\ y \\ z \\ w \end{pmatrix} * @f] */ - constexpr /*implicit*/ Vector4(T x, T y, T z, T w): Vector<4, T>(x, y, z, w) {} + constexpr /*implicit*/ Vector4(T x, T y, T z, T w) noexcept: Vector<4, T>(x, y, z, w) {} /** * @brief Constructor @@ -96,16 +96,16 @@ template class Vector4: public Vector<4, T> { * \boldsymbol v = \begin{pmatrix} v_x \\ v_y \\ v_z \\ w \end{pmatrix} * @f] */ - constexpr /*implicit*/ Vector4(const Vector3& xyz, T w): Vector<4, T>(xyz[0], xyz[1], xyz[2], w) {} + constexpr /*implicit*/ Vector4(const Vector3& xyz, T w) noexcept: Vector<4, T>(xyz[0], xyz[1], xyz[2], w) {} /** @copydoc Vector::Vector(const Vector&) */ - template constexpr explicit Vector4(const Vector<4, U>& other): Vector<4, T>(other) {} + template constexpr explicit Vector4(const Vector<4, U>& other) noexcept: Vector<4, T>(other) {} /** @brief Construct vector from external representation */ template::from(std::declval()))> constexpr explicit Vector4(const U& other): Vector<4, T>(Implementation::VectorConverter<4, T, U>::from(other)) {} /** @brief Copy constructor */ - constexpr Vector4(const Vector<4, T>& other): Vector<4, T>(other) {} + constexpr /*implicit*/ Vector4(const Vector<4, T>& other) noexcept: Vector<4, T>(other) {} /** * @brief X component diff --git a/src/Magnum/Math/instantiation.cpp b/src/Magnum/Math/instantiation.cpp index 005c0fe58..483f138fa 100644 --- a/src/Magnum/Math/instantiation.cpp +++ b/src/Magnum/Math/instantiation.cpp @@ -23,6 +23,7 @@ DEALINGS IN THE SOFTWARE. */ +#include "Magnum/Math/Bezier.h" #include "Magnum/Math/DualComplex.h" #include "Magnum/Math/DualQuaternion.h" #include "Magnum/Math/Range.h" @@ -30,14 +31,21 @@ namespace Corrade { namespace Utility { #ifndef DOXYGEN_GENERATING_OUTPUT +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; + template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; -#endif template struct ConfigurationValue>; template struct ConfigurationValue>; @@ -45,14 +53,12 @@ template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; -#endif template struct ConfigurationValue>; template struct ConfigurationValue>; @@ -63,46 +69,43 @@ template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; -#endif template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; template struct ConfigurationValue>; -#ifndef MAGNUM_TARGET_GLES template struct ConfigurationValue>; template struct ConfigurationValue>; #endif -#endif }} namespace Magnum { namespace Math { #ifndef DOXYGEN_GENERATING_OUTPUT +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 2, Float>&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 3, Float>&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 2, Float>&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 3, Float>&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 2, Double>&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<2, 3, Double>&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 2, Double>&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 3, Double>&); + template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Complex&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Complex&); -#endif template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualComplex&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualComplex&); -#endif template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualQuaternion&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualQuaternion&); -#endif template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Quaternion&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Quaternion&); -#endif /* Check proper size of GL types */ static_assert(sizeof(Vector<2, Float>) == 8, "Improper size of 2-element Float vector"); @@ -114,20 +117,16 @@ static_assert(sizeof(Vector<4, Int>) == 16, "Improper size of 4-element Int vect static_assert(sizeof(Vector<2, UnsignedInt>) == 8, "Improper size of 2-element UnsignedInt vector"); static_assert(sizeof(Vector<3, UnsignedInt>) == 12, "Improper size of 3-element UnsignedInt vector"); static_assert(sizeof(Vector<4, UnsignedInt>) == 16, "Improper size of 4-element UnsignedInt vector"); -#ifndef MAGNUM_TARGET_GLES static_assert(sizeof(Vector<2, Double>) == 16, "Improper size of 2-element Double vector"); static_assert(sizeof(Vector<3, Double>) == 24, "Improper size of 3-element Double vector"); static_assert(sizeof(Vector<4, Double>) == 32, "Improper size of 4-element Double vector"); -#endif static_assert(sizeof(RectangularMatrix<2, 2, Float>) == 16, "Improper size of 2x2 Float matrix"); static_assert(sizeof(RectangularMatrix<3, 3, Float>) == 36, "Improper size of 3x3 Float matrix"); static_assert(sizeof(RectangularMatrix<4, 4, Float>) == 64, "Improper size of 4x4 Float matrix"); -#ifndef MAGNUM_TARGET_GLES static_assert(sizeof(RectangularMatrix<2, 2, Double>) == 32, "Improper size of 2x2 Double matrix"); static_assert(sizeof(RectangularMatrix<3, 3, Double>) == 72, "Improper size of 3x3 Double matrix"); static_assert(sizeof(RectangularMatrix<4, 4, Double>) == 128, "Improper size of 4x4 Double matrix"); -#endif static_assert(sizeof(RectangularMatrix<2, 3, Float>) == 24, "Improper size of 2x3 Float matrix"); static_assert(sizeof(RectangularMatrix<3, 2, Float>) == 24, "Improper size of 3x2 Float matrix"); @@ -135,23 +134,19 @@ static_assert(sizeof(RectangularMatrix<2, 4, Float>) == 32, "Improper size of 2x static_assert(sizeof(RectangularMatrix<4, 2, Float>) == 32, "Improper size of 4x2 Float matrix"); static_assert(sizeof(RectangularMatrix<3, 4, Float>) == 48, "Improper size of 3x4 Float matrix"); static_assert(sizeof(RectangularMatrix<4, 3, Float>) == 48, "Improper size of 4x3 Float matrix"); -#ifndef MAGNUM_TARGET_GLES static_assert(sizeof(RectangularMatrix<2, 3, Double>) == 48, "Improper size of 2x3 Double matrix"); static_assert(sizeof(RectangularMatrix<3, 2, Double>) == 48, "Improper size of 3x2 Double matrix"); static_assert(sizeof(RectangularMatrix<2, 4, Double>) == 64, "Improper size of 2x4 Double matrix"); static_assert(sizeof(RectangularMatrix<4, 2, Double>) == 64, "Improper size of 4x2 Double matrix"); static_assert(sizeof(RectangularMatrix<3, 4, Double>) == 96, "Improper size of 3x4 Double matrix"); static_assert(sizeof(RectangularMatrix<4, 3, Double>) == 96, "Improper size of 4x3 Double matrix"); -#endif template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 2, Float>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 3, Float>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 4, Float>&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 2, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 3, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 4, Double>&); -#endif template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 3, Float>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 2, Float>&); @@ -159,21 +154,17 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Rec template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 2, Float>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 4, Float>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 3, Float>&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 3, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 2, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<2, 4, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 2, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<3, 4, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const RectangularMatrix<4, 3, Double>&); -#endif template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Unit&); -#endif template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<2, Float>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<3, Float>&); @@ -184,12 +175,9 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vec template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<2, UnsignedInt>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<3, UnsignedInt>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<4, UnsignedInt>&); -#ifndef MAGNUM_TARGET_GLES template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<2, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<3, Double>&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Vector<4, Double>&); #endif -#endif }} - diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 96631277f..bc4da4c0a 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -31,6 +31,9 @@ #include "Magnum/Buffer.h" #include "Magnum/Context.h" #include "Magnum/Extensions.h" +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/TransformFeedback.h" +#endif #ifndef MAGNUM_TARGET_WEBGL #include "Implementation/DebugState.h" @@ -119,7 +122,7 @@ std::size_t Mesh::indexSize(IndexType type) { case IndexType::UnsignedInt: return 4; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } Mesh::Mesh(const MeshPrimitive primitive): _primitive{primitive}, _flags{ObjectFlag::DeleteOnDestruction}, _count{0}, _baseVertex{0}, _instanceCount{1}, @@ -245,6 +248,9 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi } void Mesh::draw(AbstractShaderProgram& shader) { + /* Nothing to draw, exit without touching any state */ + if(!_count || !_instanceCount) return; + shader.use(); #ifndef MAGNUM_TARGET_GLES @@ -266,9 +272,6 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i { const Implementation::MeshState& state = *Context::current().state().mesh; - /* Nothing to draw */ - if(!count || !instanceCount) return; - (this->*state.bindImplementation)(); /* Non-instanced mesh */ @@ -363,6 +366,42 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i (this->*state.unbindImplementation)(); } +#ifndef MAGNUM_TARGET_GLES +void Mesh::drawInternal(TransformFeedback& xfb, const UnsignedInt stream, const Int instanceCount) { + const Implementation::MeshState& state = *Context::current().state().mesh; + + (this->*state.bindImplementation)(); + + /* Default stream */ + if(stream == 0) { + /* Non-instanced mesh */ + if(instanceCount == 1) glDrawTransformFeedback(GLenum(_primitive), xfb.id()); + + /* Instanced mesh */ + else glDrawTransformFeedbackInstanced(GLenum(_primitive), xfb.id(), instanceCount); + + /* Specific stream */ + } else { + /* Non-instanced mesh */ + if(instanceCount == 1) glDrawTransformFeedbackStream(GLenum(_primitive), xfb.id(), stream); + + /* Instanced mesh */ + else glDrawTransformFeedbackStreamInstanced(GLenum(_primitive), xfb.id(), stream, instanceCount); + } + + (this->*state.unbindImplementation)(); +} + +void Mesh::draw(AbstractShaderProgram& shader, TransformFeedback& xfb, UnsignedInt stream) { + /* Nothing to draw, exit without touching any state */ + if(!_instanceCount) return; + + shader.use(); + + drawInternal(xfb, stream, _instanceCount); +} +#endif + void Mesh::bindVAO() { GLuint& current = Context::current().state().mesh->currentVAO; if(current != _id) { @@ -373,7 +412,7 @@ void Mesh::bindVAO() { #elif !defined(CORRADE_TARGET_NACL) glBindVertexArrayOES(current = _id); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } } @@ -389,7 +428,7 @@ void Mesh::createImplementationVAO() { #elif !defined(CORRADE_TARGET_NACL) glGenVertexArraysOES(1, &_id); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } @@ -409,7 +448,7 @@ void Mesh::destroyImplementationVAO() { #elif !defined(CORRADE_TARGET_NACL) glDeleteVertexArraysOES(1, &_id); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -505,7 +544,7 @@ void Mesh::vertexAttribDivisorImplementationANGLE(const GLuint index, const GLui #else static_cast(index); static_cast(divisor); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #ifndef MAGNUM_TARGET_WEBGL @@ -515,7 +554,7 @@ void Mesh::vertexAttribDivisorImplementationEXT(const GLuint index, const GLuint #else static_cast(index); static_cast(divisor); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint divisor) { @@ -524,7 +563,7 @@ void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint #else static_cast(index); static_cast(divisor); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -570,7 +609,7 @@ void Mesh::drawArraysInstancedImplementationANGLE(const GLint baseVertex, const static_cast(baseVertex); static_cast(count); static_cast(instanceCount); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -582,7 +621,7 @@ void Mesh::drawArraysInstancedImplementationEXT(const GLint baseVertex, const GL static_cast(baseVertex); static_cast(count); static_cast(instanceCount); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -593,7 +632,7 @@ void Mesh::drawArraysInstancedImplementationNV(const GLint baseVertex, const GLs static_cast(baseVertex); static_cast(count); static_cast(instanceCount); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -605,7 +644,7 @@ void Mesh::drawElementsInstancedImplementationANGLE(const GLsizei count, const G static_cast(count); static_cast(indexOffset); static_cast(instanceCount); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -617,7 +656,7 @@ void Mesh::drawElementsInstancedImplementationEXT(const GLsizei count, const GLi static_cast(count); static_cast(indexOffset); static_cast(instanceCount); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -628,7 +667,7 @@ void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLin static_cast(count); static_cast(indexOffset); static_cast(instanceCount); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -637,6 +676,7 @@ void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLin #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, MeshPrimitive value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case MeshPrimitive::value: return debug << "MeshPrimitive::" #value; _c(Points) _c(LineStrip) @@ -655,21 +695,24 @@ Debug& operator<<(Debug& debug, MeshPrimitive value) { _c(Patches) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "MeshPrimitive::(invalid)"; + return debug << "MeshPrimitive(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, Mesh::IndexType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Mesh::IndexType::value: return debug << "Mesh::IndexType::" #value; _c(UnsignedByte) _c(UnsignedShort) _c(UnsignedInt) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Mesh::IndexType::(invalid)"; + return debug << "Mesh::IndexType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 8ae102e73..f20c3e342 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -602,7 +602,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * * If the mesh is indexed, the value is treated as index count, * otherwise the value is vertex count. If set to `0`, no draw commands - * are issued when calling @ref draw(). Default is `0`. + * are issued when calling @ref draw(AbstractShaderProgram&). Ignored + * when calling @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). + * Default is `0`. * @see @ref isIndexed(), @ref setBaseVertex(), @ref setInstanceCount() */ Mesh& setCount(Int count) { @@ -618,7 +620,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @return Reference to self (for method chaining) * * Sets number of vertices of which the vertex buffer will be offset - * when drawing. Default is `0`. + * when drawing. Ignored when calling + * @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). + * Default is `0`. * @see @ref setCount(), @ref setBaseInstance() * @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex} * for indexed meshes @@ -638,11 +642,16 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @return Reference to self (for method chaining) * * If set to `1`, non-instanced draw commands are issued when calling - * @ref draw(). If set to `0`, no draw commands are issued altogether. - * Default is `1`. + * @ref draw(AbstractShaderProgram&) or + * @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). + * If set to `0`, no draw commands are issued altogether. Default is + * `1`. * @see @ref setBaseInstance(), @ref setCount(), * @ref addVertexBufferInstanced() - * @requires_gl31 Extension @extension{ARB,draw_instanced} + * @requires_gl31 Extension @extension{ARB,draw_instanced} if using + * @ref draw(AbstractShaderProgram&) + * @requires_gl42 Extension @extension{ARB,transform_feedback_instanced} + * if using @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt) * @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays}, * @es_extension2{EXT,draw_instanced,draw_instanced} or * @es_extension{NV,draw_instanced} in OpenGL ES 2.0. @@ -662,6 +671,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @brief Set base instance * @return Reference to self (for method chaining) * + * Ignored when calling @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). * Default is `0`. * @see @ref setInstanceCount(), @ref setBaseVertex() * @requires_gl42 Extension @extension{ARB,base_instance} @@ -803,6 +813,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * ES 2.0 or @webgl_extension{OES,vertex_array_object} in WebGL 1.0 is * available, the vertex array object is used to hold the parameters. * + * Ignored when calling @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). + * * @see @ref maxElementIndex(), @ref maxElementsIndices(), * @ref maxElementsVertices(), @ref setCount(), @ref isIndexed(), * @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} @@ -838,6 +850,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * WebGL 1.0 is available, the associated vertex array object is bound * instead of setting up the mesh from scratch. * @see @ref setCount(), @ref setInstanceCount(), + * @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt), * @ref MeshView::draw(AbstractShaderProgram&), * @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list>), * @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray}, @@ -850,11 +863,61 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @fn_gl{DrawElementsInstancedBaseInstance}/ * @fn_gl{DrawElementsInstancedBaseVertex}/ * @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} + * @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex} + * if the mesh is indexed and @ref baseVertex() is not `0`. + * @requires_gl33 Extension @extension{ARB,instanced_arrays} if + * @ref instanceCount() is more than `1`. + * @requires_gl42 Extension @extension{ARB,base_instance} if + * @ref baseInstance() is not `0`. + * @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays}, + * @es_extension{EXT,instanced_arrays} or + * @es_extension{NV,instanced_arrays} in OpenGL ES 2.0 if + * @ref instanceCount() is more than `1`. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0 if @ref instanceCount() is more than `1`. + * @requires_gl Specifying base vertex for indexed meshes is not + * available in OpenGL ES or WebGL. */ void draw(AbstractShaderProgram& shader); - void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */ + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Draw the mesh with vertices coming out of transform feedback + * @param shader Shader to use for drawing + * @param xfb Transform feedback to use for vertex count + * @param stream Transform feedback stream ID + * + * Expects that the @p shader is compatible with this mesh, is fully + * set up and that the output buffer(s) from @p xfb are used as vertex + * buffers in this mesh. Everything set by @ref setCount(), + * @ref setBaseInstance(), @ref setBaseVertex() and @ref setIndexBuffer() + * is ignored, the mesh is drawn as non-indexed and the vertex count is + * taken from the @p xfb object. If @p stream is `0`, non-stream draw + * command is used. If @extension{ARB,vertex_array_object} (part of + * OpenGL 3.0) is available, the associated vertex array object is + * bound instead of setting up the mesh from scratch. + * @see @ref setInstanceCount(), @ref draw(AbstractShaderProgram&), + * @ref MeshView::draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt), + * @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray}, + * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, + * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray}, + * @fn_gl{DrawTransformFeedback}/@fn_gl{DrawTransformFeedbackInstanced} or + * @fn_gl{DrawTransformFeedbackStream}/@fn_gl{DrawTransformFeedbackStreamInstanced} + * @requires_gl40 Extension @extension{ARB,transform_feedback2} + * @requires_gl40 Extension @extension{ARB,transform_feedback3} if + * @p stream is not `0` + * @requires_gl42 Extension @extension{ARB,transform_feedback_instanced} + * if @ref instanceCount() is more than `1`. + */ + void draw(AbstractShaderProgram& shader, TransformFeedback& xfb, UnsignedInt stream = 0); + + /** @overload */ + void draw(AbstractShaderProgram&& shader, TransformFeedback& xfb, UnsignedInt stream = 0) { + draw(shader, xfb, stream); + } + #endif + private: enum class AttributeKind { Generic, @@ -948,6 +1011,10 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset); #endif + #ifndef MAGNUM_TARGET_GLES + void drawInternal(TransformFeedback& xfb, UnsignedInt stream, Int instanceCount); + #endif + void MAGNUM_LOCAL createImplementationDefault(); void MAGNUM_LOCAL createImplementationVAO(); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/MeshTools/RemoveDuplicates.h b/src/Magnum/MeshTools/RemoveDuplicates.h index 51abf7e2a..062fbaa48 100644 --- a/src/Magnum/MeshTools/RemoveDuplicates.h +++ b/src/Magnum/MeshTools/RemoveDuplicates.h @@ -80,11 +80,8 @@ data accordingly: std::vector positions; std::vector texCoords; -std::vector positionIndices; -std::tie(positionIndices, positions) = MeshTools::removeDuplicates(positions); - -std::vector texCoordIndices; -std::tie(texCoordIndices, texCoords) = MeshTools::removeDuplicates(texCoords); +std::vector positionIndices = MeshTools::removeDuplicates(positions); +std::vector texCoordIndices = MeshTools::removeDuplicates(texCoords); std::vector indices = MeshTools::combineIndexedArrays( std::make_pair(std::cref(positionIndices), std::ref(positions)), diff --git a/src/Magnum/MeshTools/Test/CMakeLists.txt b/src/Magnum/MeshTools/Test/CMakeLists.txt index 5a324d4b6..d511e745e 100644 --- a/src/Magnum/MeshTools/Test/CMakeLists.txt +++ b/src/Magnum/MeshTools/Test/CMakeLists.txt @@ -31,7 +31,7 @@ corrade_add_test(MeshToolsGenerateFlatNormalsTest GenerateFlatNormalsTest.cpp LI corrade_add_test(MeshToolsInterleaveTest InterleaveTest.cpp LIBRARIES Magnum) corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp LIBRARIES Magnum) corrade_add_test(MeshToolsSubdivideTest SubdivideTest.cpp LIBRARIES Magnum) -# corrade_add_test(MeshToolsSubdivideRemoveDuplicatesBenchmark SubdivideRemoveDuplicatesBenchmark.h SubdivideRemoveDuplicatesBenchmark.cpp MagnumPrimitives) +corrade_add_test(MeshToolsSubdivideRemov___Benchmark SubdivideRemoveDuplicatesBenchmark.cpp LIBRARIES MagnumPrimitives) corrade_add_test(MeshToolsTipsifyTest TipsifyTest.cpp LIBRARIES MagnumMeshTools) corrade_add_test(MeshToolsTransformTest TransformTest.cpp LIBRARIES MagnumMeshTools) diff --git a/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.cpp b/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.cpp index 91cf0e786..af48b49b5 100644 --- a/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.cpp +++ b/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.cpp @@ -23,62 +23,73 @@ DEALINGS IN THE SOFTWARE. */ -#include "SubdivideRemoveDuplicatesBenchmark.h" +#include -#include - -#include "Magnum/Primitives/Icosphere.h" +#include "Magnum/Math/Vector4.h" +#include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/RemoveDuplicates.h" #include "Magnum/MeshTools/Subdivide.h" - -QTEST_APPLESS_MAIN(Magnum::MeshTools::Test::SubdivideRemoveDuplicatesBenchmark) +#include "Magnum/Primitives/Icosphere.h" +#include "Magnum/Trade/MeshData3D.h" namespace Magnum { namespace MeshTools { namespace Test { +struct SubdivideRemoveDuplicatesBenchmark: TestSuite::Tester { + explicit SubdivideRemoveDuplicatesBenchmark(); + + void subdivide(); + void subdivideAndRemoveDuplicatesAfter(); + void subdivideAndRemoveDuplicatesInBetween(); +}; + +SubdivideRemoveDuplicatesBenchmark::SubdivideRemoveDuplicatesBenchmark() { + addBenchmarks({&SubdivideRemoveDuplicatesBenchmark::subdivide, + &SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesAfter, + &SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesInBetween}, 4, BenchmarkType::WallClock); +} + +namespace { + static Vector3 interpolator(const Vector3& a, const Vector3& b) { + return (a+b).normalized(); + } +} + void SubdivideRemoveDuplicatesBenchmark::subdivide() { - QBENCHMARK { - Primitives::Icosphere<0> icosphere; + CORRADE_BENCHMARK(3) { + Trade::MeshData3D icosphere = Primitives::Icosphere::solid(0); /* Subdivide 5 times */ - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); + for(std::size_t i = 0; i != 5; ++i) + MeshTools::subdivide(icosphere.indices(), icosphere.positions(0), interpolator); } } -void SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesMeshAfter() { - QBENCHMARK { - Primitives::Icosphere<0> icosphere; +void SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesAfter() { + CORRADE_BENCHMARK(3) { + Trade::MeshData3D icosphere = Primitives::Icosphere::solid(0); /* Subdivide 5 times */ - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); + for(std::size_t i = 0; i != 5; ++i) + MeshTools::subdivide(icosphere.indices(), icosphere.positions(0), interpolator); - MeshTools::removeDuplicates(*icosphere.indices(), *icosphere.positions(0)); + /* Remove duplicates after */ + icosphere.indices() = MeshTools::duplicate(icosphere.indices(), MeshTools::removeDuplicates(icosphere.positions(0))); } } -void SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesMeshBetween() { - QBENCHMARK { - Primitives::Icosphere<0> icosphere; +void SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesInBetween() { + CORRADE_BENCHMARK(3) { + Trade::MeshData3D icosphere = Primitives::Icosphere::solid(0); - /* Subdivide 5 times */ - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::removeDuplicates(*icosphere.indices(), *icosphere.positions(0)); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::removeDuplicates(*icosphere.indices(), *icosphere.positions(0)); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::removeDuplicates(*icosphere.indices(), *icosphere.positions(0)); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::removeDuplicates(*icosphere.indices(), *icosphere.positions(0)); - MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator); - MeshTools::removeDuplicates(*icosphere.indices(), *icosphere.positions(0)); + /* Subdivide 5 times and remove duplicates during the operation */ + for(std::size_t i = 0; i != 5; ++i) { + MeshTools::subdivide(icosphere.indices(), icosphere.positions(0), interpolator); + icosphere.indices() = MeshTools::duplicate(icosphere.indices(), MeshTools::removeDuplicates(icosphere.positions(0))); + } } } }}} + +CORRADE_TEST_MAIN(Magnum::MeshTools::Test::SubdivideRemoveDuplicatesBenchmark) + diff --git a/src/Magnum/MeshView.cpp b/src/Magnum/MeshView.cpp index 3e5b8d70f..9d84adefa 100644 --- a/src/Magnum/MeshView.cpp +++ b/src/Magnum/MeshView.cpp @@ -99,7 +99,7 @@ void MeshView::multiDrawImplementationDefault(std::initializer_list> meshes) { for(MeshView& mesh: meshes) { + /* Nothing to draw in this mesh */ + if(!mesh._count) continue; + + CORRADE_ASSERT(mesh._instanceCount == 1, "MeshView::draw(): cannot draw multiple instanced meshes", ); + #ifndef MAGNUM_TARGET_GLES2 - mesh._original.get().drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset, mesh._indexStart, mesh._indexEnd); + mesh._original.get().drawInternal(mesh._count, mesh._baseVertex, 1, mesh._indexOffset, mesh._indexStart, mesh._indexEnd); #else - mesh._original.get().drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset); + mesh._original.get().drawInternal(mesh._count, mesh._baseVertex, 1, mesh._indexOffset); #endif } } @@ -145,6 +150,9 @@ MeshView& MeshView::setIndexRange(Int first) { } void MeshView::draw(AbstractShaderProgram& shader) { + /* Nothing to draw, exit without touching any state */ + if(!_count || !_instanceCount) return; + shader.use(); #ifndef MAGNUM_TARGET_GLES @@ -156,4 +164,15 @@ void MeshView::draw(AbstractShaderProgram& shader) { #endif } +#ifndef MAGNUM_TARGET_GLES +void MeshView::draw(AbstractShaderProgram& shader, TransformFeedback& xfb, UnsignedInt stream) { + /* Nothing to draw, exit without touching any state */ + if(!_instanceCount) return; + + shader.use(); + + _original.get().drawInternal(xfb, stream, _instanceCount); +} +#endif + } diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index 516391fa3..a0570202c 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -79,6 +79,10 @@ class MAGNUM_EXPORT MeshView { * @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray} * or @fn_gl{BindVertexArray}, @fn_gl{MultiDrawArrays} or * @fn_gl{MultiDrawElements}/@fn_gl{MultiDrawElementsBaseVertex} + * @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex} + * if the mesh is indexed and @ref baseVertex() is not `0`. + * @requires_gl Specifying base vertex for indexed meshes is not + * available in OpenGL ES or WebGL. */ static void draw(AbstractShaderProgram& shader, std::initializer_list> meshes); @@ -105,10 +109,14 @@ class MAGNUM_EXPORT MeshView { /** @brief Movement is not allowed */ MeshView& operator=(MeshView&& other) = delete; + /** @brief Vertex/index count */ + Int count() const { return _count; } + /** * @brief Set vertex/index count * @return Reference to self (for method chaining) * + * Ignored when calling @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). * Default is `0`. */ MeshView& setCount(Int count) { @@ -116,12 +124,16 @@ class MAGNUM_EXPORT MeshView { return *this; } + /** @brief Base vertex */ + Int baseVertex() const { return _baseVertex; } + /** * @brief Set base vertex * @return Reference to self (for method chaining) * * Sets number of vertices of which the vertex buffer will be offset - * when drawing. Default is `0`. + * when drawing. Ignored when calling @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). + * Default is `0`. * @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex} * for indexed meshes * @requires_gl Base vertex cannot be specified for indexed meshes in @@ -143,7 +155,8 @@ class MAGNUM_EXPORT MeshView { * performance, as only a portion of vertex buffer needs to be * acccessed. On OpenGL ES 2.0 this function behaves the same as * @ref setIndexRange(Int), as index range functionality is not - * available there. + * available there. Ignored when calling + * @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). * @see @ref setCount() */ /* MinGW/MSVC needs inline also here to avoid linkage conflicts */ @@ -155,7 +168,8 @@ class MAGNUM_EXPORT MeshView { * @return Reference to self (for method chaining) * * Prefer to use @ref setIndexRange(Int, UnsignedInt, UnsignedInt) for - * better performance. + * better performance. Ignored when calling + * @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). * @see @ref setCount() */ MeshView& setIndexRange(Int first); @@ -168,7 +182,10 @@ class MAGNUM_EXPORT MeshView { * @return Reference to self (for method chaining) * * Default is `1`. - * @requires_gl31 Extension @extension{ARB,draw_instanced} + * @requires_gl31 Extension @extension{ARB,draw_instanced} if using + * @ref draw(AbstractShaderProgram&) + * @requires_gl42 Extension @extension{ARB,transform_feedback_instanced} + * if using @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt) * @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays}, * @es_extension2{EXT,draw_instanced,draw_instanced} or * @es_extension{NV,draw_instanced} in OpenGL ES 2.0. @@ -188,6 +205,7 @@ class MAGNUM_EXPORT MeshView { * @brief Set base instance * @return Reference to self (for method chaining) * + * Ignored when calling @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). * Default is `0`. * @requires_gl42 Extension @extension{ARB,base_instance} * @requires_gl Base instance cannot be specified in OpenGL ES or @@ -202,12 +220,52 @@ class MAGNUM_EXPORT MeshView { /** * @brief Draw the mesh * - * See @ref Mesh::draw() for more information. - * @see @ref draw(AbstractShaderProgram&, std::initializer_list>) + * See @ref Mesh::draw(AbstractShaderProgram&) for more information. + * @see @ref draw(AbstractShaderProgram&, std::initializer_list>), + * @ref draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt) + * @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex} + * if the mesh is indexed and @ref baseVertex() is not `0`. + * @requires_gl33 Extension @extension{ARB,instanced_arrays} if + * @ref instanceCount() is more than `1`. + * @requires_gl42 Extension @extension{ARB,base_instance} if + * @ref baseInstance() is not `0`. + * @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays}, + * @es_extension{EXT,instanced_arrays} or + * @es_extension{NV,instanced_arrays} in OpenGL ES 2.0 if + * @ref instanceCount() is more than `1`. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0 if @ref instanceCount() is more than `1`. + * @requires_gl Specifying base vertex for indexed meshes is not + * available in OpenGL ES or WebGL. */ void draw(AbstractShaderProgram& shader); void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */ + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Draw the mesh with vertices coming out of transform feedback + * + * Everything set by @ref setCount(), @ref setBaseInstance(), + * @ref setBaseVertex(), @ref setIndexRange() and @ref Mesh::setIndexBuffer() + * is ignored, the mesh is drawn as non-indexed and the vertex count is + * taken from the @p xfb object. See + * @ref Mesh::draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt) + * for more information. + * @see @ref draw(AbstractShaderProgram&) + * @requires_gl40 Extension @extension{ARB,transform_feedback2} + * @requires_gl40 Extension @extension{ARB,transform_feedback3} if + * @p stream is not `0` + * @requires_gl42 Extension @extension{ARB,transform_feedback_instanced} + * if @ref instanceCount() is more than `1`. + */ + void draw(AbstractShaderProgram& shader, TransformFeedback& xfb, UnsignedInt stream = 0); + + /** @overload */ + void draw(AbstractShaderProgram&& shader, TransformFeedback& xfb, UnsignedInt stream = 0) { + draw(shader, xfb, stream); + } + #endif + private: #ifndef MAGNUM_TARGET_WEBGL static MAGNUM_LOCAL void multiDrawImplementationDefault(std::initializer_list> meshes); diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index 52e4e4d30..7d03446ca 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -291,7 +291,6 @@ template class MultisampleTexture: public AbstractTextur /** * @copybrief Texture::invalidateImage() - * @return Reference to self (for method chaining) * * See @ref Texture::invalidateImage() for more information. */ @@ -299,7 +298,6 @@ template class MultisampleTexture: public AbstractTextur /** * @copybrief Texture::invalidateSubImage() - * @return Reference to self (for method chaining) * * See @ref Texture::invalidateSubImage() for more information. */ diff --git a/src/Magnum/OpenGL.h b/src/Magnum/OpenGL.h index e6e792a13..b8ab3f9a5 100644 --- a/src/Magnum/OpenGL.h +++ b/src/Magnum/OpenGL.h @@ -55,7 +55,15 @@ #include "MagnumExternal/OpenGL/GLES3/flextGLEmscripten.h" #endif -/* Generic OpenGL ES */ +/* Special case for desktop GLES on Windows (still links to the old opengl32.dll) */ +#elif defined(CORRADE_TARGET_WINDOWS) && defined(MAGNUM_TARGET_DESKTOP_GLES) + #ifdef MAGNUM_TARGET_GLES2 + #include "MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.h" + #else + #include "MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.h" + #endif + +/* Generic, sane OpenGL ES */ #elif defined(MAGNUM_TARGET_GLES2) #include "MagnumExternal/OpenGL/GLES2/flextGL.h" #else diff --git a/src/Magnum/PixelFormat.cpp b/src/Magnum/PixelFormat.cpp index 7059b7a38..caea62d40 100644 --- a/src/Magnum/PixelFormat.cpp +++ b/src/Magnum/PixelFormat.cpp @@ -32,6 +32,7 @@ namespace Magnum { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const PixelFormat value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case PixelFormat::value: return debug << "PixelFormat::" #value; #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) _c(Red) @@ -77,13 +78,15 @@ Debug& operator<<(Debug& debug, const PixelFormat value) { #endif _c(DepthStencil) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "PixelFormat::(invalid)"; + return debug << "PixelFormat(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const PixelType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case PixelType::value: return debug << "PixelType::" #value; _c(UnsignedByte) #ifndef MAGNUM_TARGET_GLES2 @@ -132,13 +135,15 @@ Debug& operator<<(Debug& debug, const PixelType value) { _c(Float32UnsignedInt248Rev) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "PixelType::(invalid)"; + return debug << "PixelType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const CompressedPixelFormat value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case CompressedPixelFormat::value: return debug << "CompressedPixelFormat::" #value; #ifndef MAGNUM_TARGET_GLES _c(Red) @@ -201,9 +206,10 @@ Debug& operator<<(Debug& debug, const CompressedPixelFormat value) { _c(SRGB8Alpha8Astc12x12) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "CompressedPixelFormat::(invalid)"; + return debug << "CompressedPixelFormat(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/PixelStorage.cpp b/src/Magnum/PixelStorage.cpp index 704875b9b..0b0e99971 100644 --- a/src/Magnum/PixelStorage.cpp +++ b/src/Magnum/PixelStorage.cpp @@ -153,10 +153,10 @@ std::size_t PixelStorage::pixelSize(PixelFormat format, PixelType type) { CORRADE_ASSERT(false, "AbstractImage::pixelSize(): invalid PixelType specified for depth/stencil PixelFormat", 0); } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } -std::tuple, std::size_t> PixelStorage::dataProperties(const PixelFormat format, const PixelType type, const Vector3i& size) const { +std::tuple, Math::Vector3, std::size_t> PixelStorage::dataProperties(const PixelFormat format, const PixelType type, const Vector3i& size) const { const std::size_t pixelSize = PixelStorage::pixelSize(format, type); const Math::Vector3 dataSize{ std::size_t(((( @@ -170,13 +170,13 @@ std::tuple, std::size_t> PixelStorage::d std::size_t(size.y()), #endif std::size_t(size.z())}; - const std::size_t offset = (Math::Vector3{pixelSize, dataSize.x(), dataSize.xy().product()}*Math::Vector3{_skip}).sum(); - return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3{}, pixelSize); + return std::make_tuple(Math::Vector3{pixelSize, dataSize.x(), dataSize.xy().product()}*Math::Vector3{_skip}, + size.product() ? dataSize : Math::Vector3{}, pixelSize); } #ifndef MAGNUM_TARGET_GLES -std::tuple, std::size_t> CompressedPixelStorage::dataProperties(const Vector3i& size) const { +std::tuple, Math::Vector3, std::size_t> CompressedPixelStorage::dataProperties(const Vector3i& size) const { CORRADE_ASSERT(_blockDataSize && _blockSize.product(), "CompressedPixelStorage::dataProperties(): expected non-zero storage parameters", {}); const Vector3i blockCount = (size + _blockSize - Vector3i{1})/_blockSize; @@ -186,7 +186,7 @@ std::tuple, std::size_t> CompressedPixel std::size_t(blockCount.z())}; const Vector3i skipBlockCount = (_skip + _blockSize - Vector3i{1})/_blockSize; - const std::size_t offset = (Math::Vector3{1, dataSize.x(), dataSize.xy().product()}*Math::Vector3{skipBlockCount}).sum()*_blockDataSize; + const Math::Vector3 offset = (Math::Vector3{1, dataSize.x(), dataSize.xy().product()}*Math::Vector3{skipBlockCount})*_blockDataSize; return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3{}, _blockDataSize); } diff --git a/src/Magnum/PixelStorage.h b/src/Magnum/PixelStorage.h index bd8b0420c..51b42da92 100644 --- a/src/Magnum/PixelStorage.h +++ b/src/Magnum/PixelStorage.h @@ -203,14 +203,14 @@ class MAGNUM_EXPORT PixelStorage { /** * @brief Data properties for given parameters * - * Returns byte offset, (row length, row count, layer count) and pixel - * size for image of given @p size with current pixel storage - * parameters, @p format and @p type. The offset reflects the @ref skip() - * parameter. Adding byte offset and product of the vector gives - * minimal byte count to store given data. + * Returns byte offset in each direction, (row length, row count, layer + * count) and pixel size for image of given @p size with current pixel + * storage parameters, @p format and @p type. The offset reflects the + * @ref skip() parameter. Adding byte offset and product of the vector + * gives minimal byte count to store given data. * @see @ref pixelSize() */ - std::tuple, std::size_t> dataProperties(PixelFormat format, PixelType type, const Vector3i& size) const; + std::tuple, Math::Vector3, std::size_t> dataProperties(PixelFormat format, PixelType type, const Vector3i& size) const; #ifndef DOXYGEN_GENERATING_OUTPUT protected: @@ -306,15 +306,16 @@ class MAGNUM_EXPORT CompressedPixelStorage: public PixelStorage { /** * @brief Data properties for given parameters * - * Returns byte offset, count of blocks in each dimension and block - * data size for image of given @p size with current pixel storage - * parameters. Adding byte offset and product of the vector multiplied - * with block data size gives minimal byte count to store given data. + * Returns byte offset in each dimension, count of blocks in each + * dimension and block data size for image of given @p size with + * current pixel storage parameters. Adding byte offset and product of + * the vector multiplied with block data size gives minimal byte count + * to store given data. * * Expects @ref compressedBlockSize() and @ref compressedBlockDataSize() * to be non-zero. */ - std::tuple, std::size_t> dataProperties(const Vector3i& size) const; + std::tuple, Math::Vector3, std::size_t> dataProperties(const Vector3i& size) const; /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT @@ -369,37 +370,49 @@ constexpr PixelStorage::PixelStorage() noexcept: namespace Implementation { /* Used in *Image::dataProperties() */ - template std::tuple, std::size_t> imageDataProperties(const T& image) { - std::size_t offset; - Math::Vector3 dataSize; + template std::tuple, Math::Vector, std::size_t> imageDataProperties(const T& image) { + Math::Vector3 offset, dataSize; std::size_t pixelSize; std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(image.size(), 1)); - return std::make_tuple(offset, Math::Vector::pad(dataSize), pixelSize); + return std::make_tuple(Math::Vector::pad(offset), Math::Vector::pad(dataSize), pixelSize); } #ifndef MAGNUM_TARGET_GLES2 /* Used in Compressed*Image::dataProperties() */ - template std::tuple, std::size_t> compressedImageDataProperties(const T& image) { - std::size_t offset; - Math::Vector3 blockCount; + template std::tuple, Math::Vector, std::size_t> compressedImageDataProperties(const T& image) { + Math::Vector3 offset, blockCount; std::size_t blockSize; std::tie(offset, blockCount, blockSize) = image.storage().dataProperties(Vector3i::pad(image.size(), 1)); - return std::make_tuple(offset, Math::Vector::pad(blockCount), blockSize); + return std::make_tuple(Math::Vector::pad(offset), Math::Vector::pad(blockCount), blockSize); } #endif /* Used in image query functions */ template std::size_t imageDataSizeFor(const T& image, const Math::Vector& size) { - const auto paddedSize = Vector3i::pad(size, 1); - - std::size_t offset; - Math::Vector3 dataSize; + Math::Vector3 offset, dataSize; std::size_t pixelSize; - std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), paddedSize); - - /* I would subtract also (dataSize.x() - pixelSize*paddedSize.x()) but NVidia - then complains that the buffer is too small */ - return offset + dataSize.product() - (dataSize.y() - paddedSize.y())*dataSize.x(); + std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1)); + + /* Smallest line/rectangle/cube that covers the area */ + std::size_t dataOffset = 0; + if(offset.z()) + dataOffset += offset.z(); + else if(offset.y()) { + #ifndef MAGNUM_TARGET_GLES2 + if(!image.storage().imageHeight()) + #endif + { + dataOffset += offset.y(); + } + } else if(offset.x()) { + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + if(!image.storage().rowLength()) + #endif + { + dataOffset += offset.x(); + } + } + return dataOffset + dataSize.product(); } /* Used in data size assertions */ @@ -419,14 +432,13 @@ namespace Implementation { if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) return {0, dataSize}; - std::size_t offset; - Math::Vector3 blockCount; + Math::Vector3 offset, blockCount; std::size_t blockDataSize; std::tie(offset, blockCount, blockDataSize) = image.storage().dataProperties(Vector3i::pad(size, 1)); const auto realBlockCount = Math::Vector3{(Vector3i::pad(size, 1) + image.storage().compressedBlockSize() - Vector3i{1})/image.storage().compressedBlockSize()}; - return {offset, (blockCount.product() - (blockCount.x() - realBlockCount.x()) - (blockCount.y() - realBlockCount.y())*blockCount.x())*blockDataSize}; + return {offset.sum(), (blockCount.product() - (blockCount.x() - realBlockCount.x()) - (blockCount.y() - realBlockCount.y())*blockCount.x())*blockDataSize}; } /* Used in image query functions */ @@ -447,7 +459,7 @@ namespace Implementation { #ifdef MAGNUM_TARGET_GLES2 template std::ptrdiff_t pixelStorageSkipOffsetFor(const T& image, const Math::Vector& size) { - return std::get<0>(image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1))); + return std::get<0>(image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1))).sum(); } template std::ptrdiff_t pixelStorageSkipOffset(const T& image) { return pixelStorageSkipOffsetFor(image, image.size()); diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index e360f8ef6..b91716622 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -25,7 +25,7 @@ #include "AbstractXApplication.h" -#include +#include #include "Magnum/Platform/Context.h" #include "Magnum/Version.h" @@ -162,7 +162,7 @@ int AbstractXApplication::exec() { if(_flags & Flag::Redraw) { _flags &= ~Flag::Redraw; drawEvent(); - } else Utility::sleep(5); + } else Utility::System::sleep(5); } return 0; diff --git a/src/Magnum/Platform/CMakeLists.txt b/src/Magnum/Platform/CMakeLists.txt index 1a1dbca71..b48883ac8 100644 --- a/src/Magnum/Platform/CMakeLists.txt +++ b/src/Magnum/Platform/CMakeLists.txt @@ -70,11 +70,19 @@ if(WITH_ANDROIDAPPLICATION) set(MagnumAndroidApplication_PRIVATE_HEADERS Implementation/Egl.h) + add_library(MagnumAndroidApplicationGlue OBJECT + ${ANDROID_NATIVE_APP_GLUE_SRC}) + set_target_properties(MagnumAndroidApplicationGlue PROPERTIES CORRADE_USE_PEDANTIC_FLAGS OFF) + target_compile_options(MagnumAndroidApplicationGlue PRIVATE "-fvisibility=default") + add_library(MagnumAndroidApplication STATIC ${MagnumAndroidApplication_SRCS} ${MagnumAndroidApplication_HEADERS} ${MagnumAndroidApplication_PRIVATE_HEADERS} - ${ANDROID_NATIVE_APP_GLUE_SRC}) + $) + # They just don't care, so of course the ANativeActivity_onCreate() + # function is not exported and thus the app startup fails if I don't + # disable hidden visibility for the file. target_include_directories(MagnumAndroidApplication PUBLIC ${ANDROID_NATIVE_APP_GLUE_INCLUDE_DIR}) set_target_properties(MagnumAndroidApplication PROPERTIES DEBUG_POSTFIX "-d") # Assuming that PIC is not needed because the Application lib is always @@ -222,8 +230,9 @@ if(WITH_WINDOWLESSNACLAPPLICATION) ${MagnumWindowlessNaClApplication_SRCS} ${MagnumWindowlessNaClApplication_HEADERS}) set_target_properties(MagnumWindowlessNaClApplication PROPERTIES DEBUG_POSTFIX "-d") - # Assuming that PIC is not needed because the Application lib is always - # linked to the executable and not to any intermediate shared lib + if(BUILD_STATIC_PIC) + set_target_properties(MagnumWindowlessNaClApplication PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() target_link_libraries(MagnumWindowlessNaClApplication Magnum ppapi_cpp ppapi) install(FILES ${MagnumWindowlessNaClApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) @@ -343,9 +352,10 @@ if(WITH_WINDOWLESSEGLAPPLICATION) ${MagnumWindowlessEglApplication_HEADERS} ${MagnumWindowlessEglApplication_PRIVATE_HEADERS}) set_target_properties(MagnumWindowlessEglApplication PROPERTIES DEBUG_POSTFIX "-d") + if(BUILD_STATIC_PIC) + set_target_properties(MagnumWindowlessEglApplication PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() target_link_libraries(MagnumWindowlessEglApplication Magnum EGL::EGL) - # Assuming that PIC is not needed because the Application lib is always - # linked to the executable and not to any intermediate shared lib install(FILES ${MagnumWindowlessEglApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumWindowlessEglApplication @@ -372,8 +382,9 @@ if(WITH_WINDOWLESSGLXAPPLICATION) # X11 macros are a mess, disable warnings for C-style casts set_target_properties(MagnumWindowlessGlxApplication PROPERTIES DEBUG_POSTFIX "-d") target_compile_options(MagnumWindowlessGlxApplication PRIVATE "-Wno-old-style-cast") - # Assuming that PIC is not needed because the Application lib is always - # linked to the executable and not to any intermediate shared lib + if(BUILD_STATIC_PIC) + set_target_properties(MagnumWindowlessGlxApplication PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() target_include_directories(MagnumWindowlessGlxApplication PUBLIC ${X11_INCLUDE_DIR}) target_link_libraries(MagnumWindowlessGlxApplication Magnum ${X11_LIBRARIES}) @@ -405,12 +416,13 @@ if(WITH_WINDOWLESSIOSAPPLICATION) ${MagnumWindowlessIosApplication_SRCS} ${MagnumWindowlessIosApplication_HEADERS}) set_target_properties(MagnumWindowlessIosApplication PROPERTIES DEBUG_POSTFIX "-d") + if(BUILD_STATIC_PIC) + set_target_properties(MagnumWindowlessIosApplication PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() target_link_libraries(MagnumWindowlessIosApplication Magnum EGL::EGL ${_MAGNUM_IOS_FOUNDATION_FRAMEWORK_LIBRARY}) - # Assuming that PIC is not needed because the Application lib is always - # linked to the executable and not to any intermediate shared lib install(FILES ${MagnumWindowlessIosApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumWindowlessIosApplication @@ -436,8 +448,9 @@ if(WITH_WINDOWLESSWGLAPPLICATION) ${MagnumWindowlessWglApplication_HEADERS}) set_target_properties(MagnumWindowlessWglApplication PROPERTIES DEBUG_POSTFIX "-d") target_compile_definitions(MagnumWindowlessWglApplication PRIVATE "UNICODE") - # Assuming that PIC is not needed because the Application lib is always - # linked to the executable and not to any intermediate shared lib + if(BUILD_STATIC_PIC) + set_target_properties(MagnumWindowlessWglApplication PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() target_link_libraries(MagnumWindowlessWglApplication Magnum) install(FILES ${MagnumWindowlessWglApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) @@ -469,8 +482,9 @@ if(WITH_WINDOWLESSWINDOWSEGLAPPLICATION) ${MagnumWindowlessWindowsEglApplication_PRIVATE_HEADERS}) set_target_properties(MagnumWindowlessWindowsEglApplication PROPERTIES DEBUG_POSTFIX "-d") target_compile_definitions(MagnumWindowlessWindowsEglApplication PRIVATE "UNICODE") - # Assuming that PIC is not needed because the Application lib is always - # linked to the executable and not to any intermediate shared lib + if(BUILD_STATIC_PIC) + set_target_properties(MagnumWindowlessWindowsEglApplication PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() target_link_libraries(MagnumWindowlessWindowsEglApplication Magnum EGL::EGL) install(FILES ${MagnumWindowlessWindowsEglApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) @@ -496,8 +510,9 @@ if(WITH_WINDOWLESSCGLAPPLICATION) ${MagnumWindowlessCglApplication_SRCS} ${MagnumWindowlessCglApplication_HEADERS}) set_target_properties(MagnumWindowlessCglApplication PROPERTIES DEBUG_POSTFIX "-d") - # Assuming that PIC is not needed because the Application lib is always - # linked to the executable and not to any intermediate shared lib + if(BUILD_STATIC_PIC) + set_target_properties(MagnumWindowlessCglApplication PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() target_link_libraries(MagnumWindowlessCglApplication Magnum) install(FILES ${MagnumWindowlessCglApplication_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) @@ -582,13 +597,17 @@ endif() if(NOT MAGNUM_TARGET_GLES) list(APPEND MagnumContext_SRCS ../../MagnumExternal/OpenGL/GL/flextGLPlatform.cpp) elseif(MAGNUM_TARGET_GLES AND MAGNUM_TARGET_GLES2) - if(CORRADE_TARGET_IOS) + if(CORRADE_TARGET_WINDOWS AND MAGNUM_TARGET_DESKTOP_GLES) + list(APPEND MagnumContext_SRCS ../../MagnumExternal/OpenGL/GLES2/flextGLPlatformWindowsDesktop.cpp) + elseif(CORRADE_TARGET_IOS) list(APPEND MagnumContext_SRCS ../../MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp) else() list(APPEND MagnumContext_SRCS ../../MagnumExternal/OpenGL/GLES2/flextGLPlatform.cpp) endif() elseif(MAGNUM_TARGET_GLES AND NOT MAGNUM_TARGET_GLES2) - if(CORRADE_TARGET_IOS) + if(CORRADE_TARGET_WINDOWS AND MAGNUM_TARGET_DESKTOP_GLES) + list(APPEND MagnumContext_SRCS ../../MagnumExternal/OpenGL/GLES3/flextGLPlatformWindowsDesktop.cpp) + elseif(CORRADE_TARGET_IOS) list(APPEND MagnumContext_SRCS ../../MagnumExternal/OpenGL/GLES3/flextGLPlatformIOS.cpp) else() list(APPEND MagnumContext_SRCS ../../MagnumExternal/OpenGL/GLES3/flextGLPlatform.cpp) @@ -645,7 +664,7 @@ if(NEED_EGLCONTEXT OR WITH_EGLCONTEXT) if(WITH_EGLCONTEXT) add_library(MagnumEglContext STATIC $ - ../dummy.cpp) # XCode workaround, see file comment for details + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details set_target_properties(MagnumEglContext PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) set_target_properties(MagnumEglContext PROPERTIES POSITION_INDEPENDENT_CODE ON) @@ -733,7 +752,11 @@ if(WITH_MAGNUMINFO) elseif(CORRADE_TARGET_NACL) target_link_libraries(magnum-info MagnumWindowlessNaClApplication) elseif(CORRADE_TARGET_UNIX) - target_link_libraries(magnum-info MagnumWindowlessGlxApplication) + if(MAGNUM_TARGET_GLES AND NOT MAGNUM_TARGET_DESKTOP_GLES) + target_link_libraries(magnum-info MagnumWindowlessEglApplication) + else() + target_link_libraries(magnum-info MagnumWindowlessGlxApplication) + endif() elseif(CORRADE_TARGET_WINDOWS) if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) target_link_libraries(magnum-info MagnumWindowlessWglApplication) diff --git a/src/Magnum/Platform/Context.h b/src/Magnum/Platform/Context.h index 4bb498dcc..e9d207c43 100644 --- a/src/Magnum/Platform/Context.h +++ b/src/Magnum/Platform/Context.h @@ -54,13 +54,19 @@ class Context: public Magnum::Context { * @def_gl{CONTEXT_FLAGS}, @def_gl{NUM_EXTENSIONS}, * @fn_gl{GetString} with @def_gl{EXTENSIONS} */ - explicit Context(Int argc, char** argv): Context{NoCreate, argc, argv} { create(); } + explicit Context(Int argc, const char** argv): Context{NoCreate, argc, argv} { create(); } + + /** @overload */ + explicit Context(Int argc, char** argv): Context{argc, const_cast(argv)} {} + + /** @overload */ + explicit Context(Int argc, std::nullptr_t argv): Context{argc, static_cast(argv)} {} #ifdef MAGNUM_BUILD_DEPRECATED - /** @copybrief Context(Int, char**) - * @deprecated Use @ref Context(Int, char**) instead. + /** @copybrief Context(Int, const char**) + * @deprecated Use @ref Context(Int, const char**) instead. */ - CORRADE_DEPRECATED("use Context(Int, char**) instead") explicit Context(): Context(0, nullptr) {} + CORRADE_DEPRECATED("use Context(Int, const char**) instead") explicit Context(): Context(0, nullptr) {} #endif /** @@ -71,13 +77,19 @@ class Context: public Magnum::Context { * left in empty state. Use @ref create() or @ref tryCreate() to * complete the setup. */ - explicit Context(NoCreateT, Int argc, char** argv): + explicit Context(NoCreateT, Int argc, const char** argv): #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) Magnum::Context{NoCreate, argc, argv, flextGLInit} {} #else Magnum::Context{NoCreate, argc, argv, nullptr} {} #endif + /** @overload */ + explicit Context(NoCreateT, Int argc, char** argv): Context{NoCreate, argc, const_cast(argv)} {} + + /** @overload */ + explicit Context(NoCreateT, Int argc, std::nullptr_t argv): Context{NoCreate, argc, static_cast(argv)} {} + /** * @brief Complete the context setup and exit on failure * diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index ff2ffddc7..65e1d7780 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -27,6 +27,7 @@ #include "GlfwApplication.h" #include +#include #include "Magnum/Version.h" #include "Magnum/Platform/Context.h" @@ -89,7 +90,7 @@ bool GlfwApplication::tryCreateContext(const Configuration& configuration) { glfwWindowHint(GLFW_ICONIFIED, flags >= Configuration::WindowFlag::Minimized); glfwWindowHint(GLFW_FLOATING, flags >= Configuration::WindowFlag::Floating); } - glfwWindowHint(GLFW_FLOATING, configuration.windowFlags() >= Configuration::WindowFlag::Focused); + glfwWindowHint(GLFW_FOCUSED, configuration.windowFlags() >= Configuration::WindowFlag::Focused); /* Context window hints */ glfwWindowHint(GLFW_SAMPLES, configuration.sampleCount()); @@ -162,13 +163,15 @@ int GlfwApplication::exec() { } void GlfwApplication::staticKeyEvent(GLFWwindow*, int key, int, int action, int mods) { - KeyEvent e(static_cast(key), {static_cast(mods)}); + KeyEvent e(static_cast(key), {static_cast(mods)}, action == GLFW_REPEAT); if(action == GLFW_PRESS) { _instance->keyPressEvent(e); } else if(action == GLFW_RELEASE) { _instance->keyReleaseEvent(e); - } /* we don't handle GLFW_REPEAT */ + } else if(action == GLFW_REPEAT) { + _instance->keyPressEvent(e); + } } void GlfwApplication::staticMouseMoveEvent(GLFWwindow* window, double x, double y) { @@ -187,13 +190,22 @@ void GlfwApplication::staticMouseEvent(GLFWwindow*, int button, int action, int } void GlfwApplication::staticMouseScrollEvent(GLFWwindow* window, double xoffset, double yoffset) { - MouseScrollEvent e(Vector2d{xoffset, yoffset}, KeyEvent::getCurrentGlfwModifiers(window)); + MouseScrollEvent e(Vector2{Float(xoffset), Float(yoffset)}, KeyEvent::getCurrentGlfwModifiers(window)); _instance->mouseScrollEvent(e); + #ifdef MAGNUM_BUILD_DEPRECATED if(yoffset != 0.0) { + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif MouseEvent e1((yoffset > 0.0) ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, KeyEvent::getCurrentGlfwModifiers(window)); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif _instance->mousePressEvent(e1); } + #endif } void GlfwApplication::staticErrorCallback(int, const char* description) { @@ -212,7 +224,7 @@ auto GlfwApplication::KeyEvent::getCurrentGlfwModifiers(GLFWwindow* window) -> M if(glfwGetKey(window, Int(Key::LeftCtrl)) || glfwGetKey(window, Int(Key::RightCtrl))) mods |= Modifier::Ctrl; if(glfwGetKey(window, Int(Key::RightSuper))) - mods |= Modifier::AltGr; + mods |= Modifier::Super; return mods; } @@ -234,6 +246,17 @@ GlfwApplication::Configuration::Configuration(): GlfwApplication::Configuration::~Configuration() = default; +#if defined(DOXYGEN_GENERATING_OUTPUT) || GLFW_VERSION_MAJOR*100 + GLFW_VERSION_MINOR >= 302 +std::string GlfwApplication::KeyEvent::keyName(const Key key) { + /* It can return null, so beware */ + return Utility::String::fromArray(glfwGetKeyName(int(key), 0)); +} + +std::string GlfwApplication::KeyEvent::keyName() const { + return keyName(_key); +} +#endif + template class BasicScreen; template class BasicScreenedApplication; diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 77e82bf72..8613213f5 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -211,17 +211,6 @@ class GlfwApplication { /** @{ @name Mouse handling */ public: - /** - * @brief Mouse cursor - * - * @see @ref setMouseCursor() - */ - enum class MouseCursor: int { - Default = GLFW_CURSOR_NORMAL, /**< Default cursor provided by parent window */ - Hidden = GLFW_CURSOR_HIDDEN, /**< Hidden cursor */ - None = GLFW_CURSOR_DISABLED /**< No cursor */ - }; - /** @brief Warp mouse cursor to given coordinates */ void warpCursor(const Vector2i& position) { glfwSetCursorPos(_window, Double(position.x()), Double(position.y())); @@ -243,16 +232,10 @@ class GlfwApplication { * * Called when any mouse button is pressed and mouse is moved. Default * implementation does nothing. - * @see @ref setMouseTracking() */ virtual void mouseMoveEvent(MouseMoveEvent& event); - /** - * @brief Mouse scroll event - * - * Called when a scrolling device is used (mouse wheel or scrolling area - * on touchpad). Default implementation does nothing. - */ + /** @copydoc Sdl2Application::mouseScrollEvent() */ virtual void mouseScrollEvent(MouseScrollEvent& event); /*@}*/ @@ -293,7 +276,7 @@ class GlfwApplication::Configuration { * @see @ref Flags, @ref setFlags(), @ref Context::Flag */ enum class Flag: Int { - #ifdef GLFW_CONTEXT_NO_ERROR + #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_CONTEXT_NO_ERROR) /** * Specifies whether errors should be generated by the context. * If enabled, situations that would have generated errors instead @@ -325,7 +308,7 @@ class GlfwApplication::Configuration { Resizeable = 1 << 1, /**< Resizeable window */ Hidden = 1 << 2, /**< Hidden window */ - #ifdef GLFW_MAXIMIZED + #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_MAXIMIZED) /** * Maximized window * @@ -517,10 +500,33 @@ class GlfwApplication::InputEvent { * @ref MouseEvent::modifiers() */ enum class Modifier: Int { - Shift = GLFW_MOD_SHIFT, /**< Shift */ - Ctrl = GLFW_MOD_CONTROL, /**< Ctrl */ - Alt = GLFW_MOD_ALT, /**< Alt */ - AltGr = GLFW_MOD_SUPER /**< AltGr */ + /** + * Shift + * + * @see @ref KeyEvent::Key::LeftShift, @ref KeyEvent::Key::RightShift + */ + Shift = GLFW_MOD_SHIFT, + + /** + * Ctrl + * + * @see @ref KeyEvent::Key::LeftCtrl, @ref KeyEvent::Key::RightCtrl + */ + Ctrl = GLFW_MOD_CONTROL, + + /** + * Alt + * + * @see @ref KeyEvent::Key::LeftAlt, @ref KeyEvent::Key::RightAlt + */ + Alt = GLFW_MOD_ALT, + + /** + * Super key (Windows/⌘) + * + * @see @ref KeyEvent::Key::LeftSuper, @ref KeyEvent::Key::RightSuper + */ + Super = GLFW_MOD_SUPER }; /** @@ -563,7 +569,7 @@ CORRADE_ENUMSET_OPERATORS(GlfwApplication::InputEvent::Modifiers) /** @brief Key event -@see @ref keyPressEvent() +@see @ref keyPressEvent(), @ref keyReleaseEvent() */ class GlfwApplication::KeyEvent: public GlfwApplication::InputEvent { friend GlfwApplication; @@ -575,84 +581,142 @@ class GlfwApplication::KeyEvent: public GlfwApplication::InputEvent { * @see @ref key() */ enum class Key: Int { - Unknown = GLFW_KEY_UNKNOWN, /**< Unknown key */ - - Enter = GLFW_KEY_ENTER, /**< Enter */ - Esc = GLFW_KEY_ESCAPE, /**< Escape */ - - Up = GLFW_KEY_UP, /**< Up arrow */ - Down = GLFW_KEY_DOWN, /**< Down arrow */ - Left = GLFW_KEY_LEFT, /**< Left arrow */ - Right = GLFW_KEY_RIGHT, /**< Right arrow */ - Home = GLFW_KEY_HOME, /**< Home */ - End = GLFW_KEY_END, /**< End */ - PageUp = GLFW_KEY_PAGE_UP, /**< Page up */ - PageDown = GLFW_KEY_PAGE_DOWN, /**< Page down */ - Backspace = GLFW_KEY_BACKSPACE, /**< Backspace */ - Insert = GLFW_KEY_INSERT, /**< Insert */ - Delete = GLFW_KEY_DELETE, /**< Delete */ - - F1 = GLFW_KEY_F1, /**< F1 */ - F2 = GLFW_KEY_F2, /**< F2 */ - F3 = GLFW_KEY_F3, /**< F3 */ - F4 = GLFW_KEY_F4, /**< F4 */ - F5 = GLFW_KEY_F5, /**< F5 */ - F6 = GLFW_KEY_F6, /**< F6 */ - F7 = GLFW_KEY_F7, /**< F7 */ - F8 = GLFW_KEY_F8, /**< F8 */ - F9 = GLFW_KEY_F9, /**< F9 */ - F10 = GLFW_KEY_F10, /**< F10 */ - F11 = GLFW_KEY_F11, /**< F11 */ - F12 = GLFW_KEY_F12, /**< F12 */ - - Space = ' ', /**< Space */ - Tab = '\t', /**< Tab */ - Comma = ',', /**< Comma */ - Period = '.', /**< Period */ - Minus = '-', /**< Minus */ - Plus = '+', /**< Plus */ - Slash = '/', /**< Slash */ - Percent = '%', /**< Percent */ - Smicolon = ';', /**< Semicolon */ - 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 */ + Unknown = GLFW_KEY_UNKNOWN, /**< Unknown key */ + + /** + * Left Shift + * + * @see @ref InputEvent::Modifier::Shift + */ + LeftShift = GLFW_KEY_LEFT_SHIFT, + + /** + * Right Shift + * + * @see @ref InputEvent::Modifier::Shift + */ + RightShift = GLFW_KEY_RIGHT_SHIFT, + + /** + * Left Ctrl + * + * @see @ref InputEvent::Modifier::Ctrl + */ + LeftCtrl = GLFW_KEY_LEFT_CONTROL, + + /** + * Right Ctrl + * + * @see @ref InputEvent::Modifier::Ctrl + */ + RightCtrl = GLFW_KEY_RIGHT_CONTROL, + + /** + * Left Alt + * + * @see @ref InputEvent::Modifier::Alt + */ + LeftAlt = GLFW_KEY_LEFT_ALT, + + /** + * Right Alt + * + * @see @ref InputEvent::Modifier::Alt + */ + RightAlt = GLFW_KEY_RIGHT_ALT, + + /** + * Left Super key (Windows/⌘) + * + * @see @ref InputEvent::Modifier::Super + */ + LeftSuper = GLFW_KEY_LEFT_SUPER, + + /** + * Right Super key (Windows/⌘) + * + * @see @ref InputEvent::Modifier::Super + */ + RightSuper = GLFW_KEY_RIGHT_SUPER, + + Enter = GLFW_KEY_ENTER, /**< Enter */ + Esc = GLFW_KEY_ESCAPE, /**< Escape */ + + Up = GLFW_KEY_UP, /**< Up arrow */ + Down = GLFW_KEY_DOWN, /**< Down arrow */ + Left = GLFW_KEY_LEFT, /**< Left arrow */ + Right = GLFW_KEY_RIGHT, /**< Right arrow */ + Home = GLFW_KEY_HOME, /**< Home */ + End = GLFW_KEY_END, /**< End */ + PageUp = GLFW_KEY_PAGE_UP, /**< Page up */ + PageDown = GLFW_KEY_PAGE_DOWN, /**< Page down */ + Backspace = GLFW_KEY_BACKSPACE, /**< Backspace */ + Insert = GLFW_KEY_INSERT, /**< Insert */ + Delete = GLFW_KEY_DELETE, /**< Delete */ + + F1 = GLFW_KEY_F1, /**< F1 */ + F2 = GLFW_KEY_F2, /**< F2 */ + F3 = GLFW_KEY_F3, /**< F3 */ + F4 = GLFW_KEY_F4, /**< F4 */ + F5 = GLFW_KEY_F5, /**< F5 */ + F6 = GLFW_KEY_F6, /**< F6 */ + F7 = GLFW_KEY_F7, /**< F7 */ + F8 = GLFW_KEY_F8, /**< F8 */ + F9 = GLFW_KEY_F9, /**< F9 */ + F10 = GLFW_KEY_F10, /**< F10 */ + F11 = GLFW_KEY_F11, /**< F11 */ + F12 = GLFW_KEY_F12, /**< F12 */ + + Space = GLFW_KEY_SPACE, /**< Space */ + Tab = GLFW_KEY_TAB, /**< Tab */ + Comma = GLFW_KEY_COMMA, /**< Comma */ + Period = GLFW_KEY_PERIOD, /**< Period */ + Minus = GLFW_KEY_MINUS, /**< Minus */ + /* Note: This may only be represented as SHIFT + = */ + Plus = '+', /**< Plus */ + Slash = GLFW_KEY_SLASH, /**< Slash */ + /* Note: This may only be represented as SHIFT + 5 */ + Percent = '%', /**< Percent */ + Smicolon = GLFW_KEY_SEMICOLON, /**< Semicolon */ + Equal = GLFW_KEY_EQUAL, /**< Equal */ + + Zero = GLFW_KEY_0, /**< Zero */ + One = GLFW_KEY_1, /**< One */ + Two = GLFW_KEY_2, /**< Two */ + Three = GLFW_KEY_3, /**< Three */ + Four = GLFW_KEY_4, /**< Four */ + Five = GLFW_KEY_5, /**< Five */ + Six = GLFW_KEY_6, /**< Six */ + Seven = GLFW_KEY_7, /**< Seven */ + Eight = GLFW_KEY_8, /**< Eight */ + Nine = GLFW_KEY_9, /**< Nine */ + + A = GLFW_KEY_A, /**< Letter A */ + B = GLFW_KEY_B, /**< Letter B */ + C = GLFW_KEY_C, /**< Letter C */ + D = GLFW_KEY_D, /**< Letter D */ + E = GLFW_KEY_E, /**< Letter E */ + F = GLFW_KEY_F, /**< Letter F */ + G = GLFW_KEY_G, /**< Letter G */ + H = GLFW_KEY_H, /**< Letter H */ + I = GLFW_KEY_I, /**< Letter I */ + J = GLFW_KEY_J, /**< Letter J */ + K = GLFW_KEY_K, /**< Letter K */ + L = GLFW_KEY_L, /**< Letter L */ + M = GLFW_KEY_M, /**< Letter M */ + N = GLFW_KEY_N, /**< Letter N */ + O = GLFW_KEY_O, /**< Letter O */ + P = GLFW_KEY_P, /**< Letter P */ + Q = GLFW_KEY_Q, /**< Letter Q */ + R = GLFW_KEY_R, /**< Letter R */ + S = GLFW_KEY_S, /**< Letter S */ + T = GLFW_KEY_T, /**< Letter T */ + U = GLFW_KEY_U, /**< Letter U */ + V = GLFW_KEY_V, /**< Letter V */ + W = GLFW_KEY_W, /**< Letter W */ + X = GLFW_KEY_X, /**< Letter X */ + Y = GLFW_KEY_Y, /**< Letter Y */ + Z = GLFW_KEY_Z, /**< Letter Z */ /* Function keys */ CapsLock = GLFW_KEY_CAPS_LOCK, /**< Caps lock */ @@ -677,36 +741,60 @@ class GlfwApplication::KeyEvent: public GlfwApplication::InputEvent { NumAdd = GLFW_KEY_KP_ADD, /**< Numpad add */ NumEnter = GLFW_KEY_KP_ENTER, /**< Numpad enter */ NumEqual = GLFW_KEY_KP_EQUAL, /**< Numpad equal */ - LeftShift = GLFW_KEY_LEFT_SHIFT, /**< Left shift */ - LeftCtrl = GLFW_KEY_LEFT_CONTROL, /**< Left control */ - LeftAlt = GLFW_KEY_LEFT_ALT, /**< Left alt */ - LeftSuper = GLFW_KEY_LEFT_SUPER, /**< Left super */ - RightShift = GLFW_KEY_RIGHT_SHIFT, /**< Right shift */ - RightCtrl = GLFW_KEY_RIGHT_CONTROL, /**< Right control */ - RightAlt = GLFW_KEY_RIGHT_ALT, /**< Right alt */ - RightSuper = GLFW_KEY_RIGHT_SUPER, /**< Right super */ Menu = GLFW_KEY_MENU /**< Menu */ }; - /** @brief Key */ + #if defined(DOXYGEN_GENERATING_OUTPUT) || GLFW_VERSION_MAJOR*100 + GLFW_VERSION_MINOR >= 302 + /** + * @brief Name for given key + * + * Human-readable localized UTF-8 name for given @p key, intended for + * displaying to the user in e.g. key binding configuration. If there + * is no name for given key, empty string is returned. + * @see @ref keyName(Key) + * @note Supported since GLFW 3.2. + */ + static std::string keyName(Key key); + #endif + + /** @copydoc Sdl2Application::KeyEvent::key() */ constexpr Key key() const { return _key; } + #if defined(DOXYGEN_GENERATING_OUTPUT) || GLFW_VERSION_MAJOR*100 + GLFW_VERSION_MINOR >= 302 + /** + * @brief Key name + * + * Human-readable localized UTF-8 name for the key returned by + * @ref key(), intended for displaying to the user in e.g. + * key binding configuration. If there is no name for that key, empty + * string is returned. + * @see @ref keyName(Key) + * @note Supported since GLFW 3.2. + */ + std::string keyName() const; + #endif + /** @brief Modifiers */ constexpr Modifiers modifiers() const { return _modifiers; } + /** @copydoc Sdl2Application::KeyEvent::isRepeated() */ + constexpr bool isRepeated() const { return _repeated; } + private: static Modifiers getCurrentGlfwModifiers(GLFWwindow* window); - constexpr KeyEvent(Key key, Modifiers modifiers): _key(key), _modifiers(modifiers) {} + constexpr KeyEvent(Key key, Modifiers modifiers, bool repeated): _key{key}, _modifiers{modifiers}, _repeated{repeated} {} const Key _key; const Modifiers _modifiers; + const bool _repeated; }; /** @brief Mouse event -@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() +@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(), + @ref mouseReleaseEvent() */ class GlfwApplication::MouseEvent: public GlfwApplication::InputEvent { friend GlfwApplication; @@ -730,8 +818,19 @@ class GlfwApplication::MouseEvent: public GlfwApplication::InputEvent { Button7 = GLFW_MOUSE_BUTTON_7, /**< Mouse button 7 */ Button8 = GLFW_MOUSE_BUTTON_8, /**< Mouse button 8 */ - WheelUp = GLFW_MOUSE_BUTTON_LAST + 1, /**< Mouse wheel up */ - WheelDown = GLFW_MOUSE_BUTTON_LAST + 2 /**< Mouse wheel down */ + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * Wheel up + * @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead. + */ + WheelUp CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = GLFW_MOUSE_BUTTON_LAST + 1, + + /** + * Wheel down + * @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead. + */ + WheelDown CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = GLFW_MOUSE_BUTTON_LAST + 2 + #endif }; /** @brief Button */ @@ -779,15 +878,15 @@ class GlfwApplication::MouseScrollEvent: public GlfwApplication::InputEvent { public: /** @brief Scroll offset */ - constexpr Vector2d offset() const { return _offset; } + constexpr Vector2 offset() const { return _offset; } /** @brief Modifiers */ constexpr Modifiers modifiers() const { return _modifiers; } private: - constexpr MouseScrollEvent(const Vector2d& offset, Modifiers modifiers): _offset(offset), _modifiers(modifiers) {} + constexpr MouseScrollEvent(const Vector2& offset, Modifiers modifiers): _offset(offset), _modifiers(modifiers) {} - const Vector2d _offset; + const Vector2 _offset; const Modifiers _modifiers; }; diff --git a/src/Magnum/Platform/MacOSXBundleInfo.plist.in b/src/Magnum/Platform/MacOSXBundleInfo.plist.in index eaac87c6a..52216bc47 100644 --- a/src/Magnum/Platform/MacOSXBundleInfo.plist.in +++ b/src/Magnum/Platform/MacOSXBundleInfo.plist.in @@ -19,7 +19,5 @@ opengles-2 - NSHighResolutionCapable - diff --git a/src/Magnum/Platform/NaClApplication.cpp b/src/Magnum/Platform/NaClApplication.cpp index 9dafcd8c9..afe153845 100644 --- a/src/Magnum/Platform/NaClApplication.cpp +++ b/src/Magnum/Platform/NaClApplication.cpp @@ -192,10 +192,17 @@ bool NaClApplication::HandleInputEvent(const pp::InputEvent& event) { case PP_INPUTEVENT_TYPE_WHEEL: { pp::WheelInputEvent wheelEvent(event); - if(Math::TypeTraits::equals(wheelEvent.GetDelta().y(), 0.0f)) return false; - MouseEvent e(wheelEvent.GetDelta().y() > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {}, static_cast(wheelEvent.GetModifiers())); - mousePressEvent(e); + MouseScrollEvent e{{wheelEvent.GetDelta().x(), wheelEvent.GetDelta().y()}, static_cast(wheelEvent.GetModifiers())}; + mouseScrollEvent(e); + #ifdef MAGNUM_BUILD_DEPRECATED + if(!Math::TypeTraits::equals(wheelEvent.GetDelta().y(), 0.0f)) { + MouseEvent e2(wheelEvent.GetDelta().y() > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {}, static_cast(wheelEvent.GetModifiers())); + mousePressEvent(e2); + if(!e.isAccepted() && !e2.isAccepted()) return false; + } else if(!e.isAccepted()) return false; + #else if(!e.isAccepted()) return false; + #endif break; } @@ -261,6 +268,7 @@ void NaClApplication::keyReleaseEvent(KeyEvent&) {} void NaClApplication::mousePressEvent(MouseEvent&) {} void NaClApplication::mouseReleaseEvent(MouseEvent&) {} void NaClApplication::mouseMoveEvent(MouseMoveEvent&) {} +void NaClApplication::mouseScrollEvent(MouseScrollEvent&) {} template class BasicScreen; template class BasicScreenedApplication; diff --git a/src/Magnum/Platform/NaClApplication.h b/src/Magnum/Platform/NaClApplication.h index 488b4e742..29c22ef4b 100644 --- a/src/Magnum/Platform/NaClApplication.h +++ b/src/Magnum/Platform/NaClApplication.h @@ -204,6 +204,7 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public class KeyEvent; class MouseEvent; class MouseMoveEvent; + class MouseScrollEvent; /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ #ifdef DOXYGEN_GENERATING_OUTPUT @@ -355,6 +356,16 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public */ virtual void mouseMoveEvent(MouseMoveEvent& event); + /** + * @brief Mouse scroll event + * + * Called when a scrolling device is used (mouse wheel or scrolling + * area on a touchpad). Default implementation does nothing. If you + * accept the event, call @ref InputEvent::setAccepted() "setAccepted()" + * on it, otherwise the event will be propagated to the browser. + */ + virtual void mouseScrollEvent(MouseScrollEvent& event); + /*@}*/ private: @@ -650,7 +661,8 @@ class NaClApplication::KeyEvent: public NaClApplication::InputEvent { @brief Mouse event See also @ref InputEvent for more information. -@see @ref MouseMoveEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() +@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(), + @ref mouseReleaseEvent() */ class NaClApplication::MouseEvent: public NaClApplication::InputEvent { friend NaClApplication; @@ -665,8 +677,20 @@ class NaClApplication::MouseEvent: public NaClApplication::InputEvent { Left = PP_INPUTEVENT_MOUSEBUTTON_LEFT, /**< Left button */ Middle = PP_INPUTEVENT_MOUSEBUTTON_MIDDLE, /**< Middle button */ Right = PP_INPUTEVENT_MOUSEBUTTON_RIGHT, /**< Right button */ - WheelUp = 0xFFFF01, /**< Wheel up */ - WheelDown = 0xFFFF02 /**< Wheel down */ + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * Wheel up + * @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead. + */ + WheelUp CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = 0xFFFF01, + + /** + * Wheel down + * @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead. + */ + WheelDown CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = 0xFFFF02 + #endif }; /** @brief Button */ @@ -692,7 +716,7 @@ class NaClApplication::MouseEvent: public NaClApplication::InputEvent { @brief Mouse move event See also @ref InputEvent for more information. -@see @ref MouseEvent, @ref mouseMoveEvent() +@see @ref MouseEvent, @ref MouseScrollEvent, @ref mouseMoveEvent() */ class NaClApplication::MouseMoveEvent: public NaClApplication::InputEvent { friend NaClApplication; @@ -714,6 +738,25 @@ class NaClApplication::MouseMoveEvent: public NaClApplication::InputEvent { const Vector2i _position, _relativePosition; }; +/** +@brief Mouse scroll event + +See also @ref InputEvent for more information. +@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent() +*/ +class NaClApplication::MouseScrollEvent: public NaClApplication::InputEvent { + friend NaClApplication; + + public: + /** @brief Scroll offset */ + constexpr Vector2 offset() const { return _offset; } + + private: + constexpr MouseScrollEvent(const Vector2& offset, Modifiers modifiers): InputEvent{modifiers}, _offset{offset} {} + + const Vector2 _offset; +}; + CORRADE_ENUMSET_OPERATORS(NaClApplication::Flags) namespace Implementation { diff --git a/src/Magnum/Platform/ScreenedApplication.hpp b/src/Magnum/Platform/ScreenedApplication.hpp index ef4abb1b2..b2b1c43a9 100644 --- a/src/Magnum/Platform/ScreenedApplication.hpp +++ b/src/Magnum/Platform/ScreenedApplication.hpp @@ -1,3 +1,5 @@ +#ifndef Magnum_Platform_ScreenedApplication_hpp +#define Magnum_Platform_ScreenedApplication_hpp /* This file is part of Magnum. @@ -141,3 +143,5 @@ template void BasicScreenedApplication::mouseMov } }} + +#endif diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index aeb6b981c..30b6ec26f 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -52,6 +52,7 @@ Sdl2Application::InputEvent::Modifiers fixedModifiers(Uint16 mod) { if(modifiers & Sdl2Application::InputEvent::Modifier::Shift) modifiers |= Sdl2Application::InputEvent::Modifier::Shift; if(modifiers & Sdl2Application::InputEvent::Modifier::Ctrl) modifiers |= Sdl2Application::InputEvent::Modifier::Ctrl; if(modifiers & Sdl2Application::InputEvent::Modifier::Alt) modifiers |= Sdl2Application::InputEvent::Modifier::Alt; + if(modifiers & Sdl2Application::InputEvent::Modifier::Super) modifiers |= Sdl2Application::InputEvent::Modifier::Alt; return modifiers; } @@ -186,6 +187,9 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) { version to the one specified, which is completely useless behavior. */ #ifndef CORRADE_TARGET_APPLE constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; + #ifdef CORRADE_TARGET_WINDOWS + constexpr static const char intelVendorString[] = "Intel"; + #endif constexpr static const char amdVendorString[] = "ATI Technologies Inc."; const char* vendorString; #endif @@ -194,8 +198,11 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) { /* Sorry about the UGLY code, HOPEFULLY THERE WON'T BE MORE WORKAROUNDS */ || (vendorString = reinterpret_cast(glGetString(GL_VENDOR)), (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || + #ifdef CORRADE_TARGET_WINDOWS + std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || + #endif std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) - && !_context->isDriverWorkaroundDisabled("amd-nv-no-forward-compatible-core-context")) + && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context")) #endif )) { /* Don't print any warning when doing the NV workaround, because the @@ -273,11 +280,13 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) { return true; } +#ifndef CORRADE_TARGET_EMSCRIPTEN Vector2i Sdl2Application::windowSize() { Vector2i size; SDL_GetWindowSize(_window, &size.x(), &size.y()); return size; } +#endif void Sdl2Application::swapBuffers() { #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -368,21 +377,42 @@ void Sdl2Application::mainLoop() { case SDL_KEYDOWN: case SDL_KEYUP: { - KeyEvent e(static_cast(event.key.keysym.sym), fixedModifiers(event.key.keysym.mod)); + KeyEvent e(static_cast(event.key.keysym.sym), fixedModifiers(event.key.keysym.mod), event.key.repeat != 0); event.type == SDL_KEYDOWN ? keyPressEvent(e) : keyReleaseEvent(e); } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { - MouseEvent e(static_cast(event.button.button), {event.button.x, event.button.y}); + MouseEvent e(static_cast(event.button.button), {event.button.x, event.button.y} + #ifndef CORRADE_TARGET_EMSCRIPTEN + , event.button.clicks + #endif + ); event.type == SDL_MOUSEBUTTONDOWN ? mousePressEvent(e) : mouseReleaseEvent(e); } break; - case SDL_MOUSEWHEEL: + case SDL_MOUSEWHEEL: { + MouseScrollEvent e{{Float(event.wheel.x), Float(event.wheel.y)}}; + mouseScrollEvent(e); + + #ifdef MAGNUM_BUILD_DEPRECATED if(event.wheel.y != 0) { - MouseEvent e(event.wheel.y > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {event.wheel.x, event.wheel.y}); + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif + MouseEvent e(event.wheel.y > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {event.wheel.x, event.wheel.y} + #ifndef CORRADE_TARGET_EMSCRIPTEN + , 0 + #endif + ); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif mousePressEvent(e); - } break; + } + #endif + } break; case SDL_MOUSEMOTION: { MouseMoveEvent e({event.motion.x, event.motion.y}, {event.motion.xrel, event.motion.yrel}, static_cast(event.motion.state)); @@ -390,7 +420,12 @@ void Sdl2Application::mainLoop() { break; } - #ifndef CORRADE_TARGET_EMSCRIPTEN + case SDL_MULTIGESTURE: { + MultiGestureEvent e({event.mgesture.x, event.mgesture.y}, event.mgesture.dTheta, event.mgesture.dDist, event.mgesture.numFingers); + multiGestureEvent(e); + break; + } + case SDL_TEXTINPUT: { TextInputEvent e{{event.text.text, std::strlen(event.text.text)}}; textInputEvent(e); @@ -400,7 +435,6 @@ void Sdl2Application::mainLoop() { TextEditingEvent e{{event.edit.text, std::strlen(event.text.text)}, event.edit.start, event.edit.length}; textEditingEvent(e); } break; - #endif case SDL_QUIT: #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -457,12 +491,32 @@ void Sdl2Application::setMouseLocked(bool enabled) { #endif } -#ifndef CORRADE_TARGET_EMSCRIPTEN +bool Sdl2Application::isTextInputActive() { + #ifndef CORRADE_TARGET_EMSCRIPTEN + return SDL_IsTextInputActive(); + #else + return _isTextInputActive; + #endif +} + +void Sdl2Application::startTextInput() { + SDL_StartTextInput(); + #ifdef CORRADE_TARGET_EMSCRIPTEN + _isTextInputActive = true; + #endif +} + +void Sdl2Application::stopTextInput() { + SDL_StopTextInput(); + #ifdef CORRADE_TARGET_EMSCRIPTEN + _isTextInputActive = false; + #endif +} + void Sdl2Application::setTextInputRect(const Range2Di& rect) { SDL_Rect r{rect.min().x(), rect.min().y(), rect.sizeX(), rect.sizeY()}; SDL_SetTextInputRect(&r); } -#endif void Sdl2Application::tickEvent() { /* If this got called, the tick event is not implemented by user and thus @@ -476,11 +530,10 @@ void Sdl2Application::keyReleaseEvent(KeyEvent&) {} void Sdl2Application::mousePressEvent(MouseEvent&) {} void Sdl2Application::mouseReleaseEvent(MouseEvent&) {} void Sdl2Application::mouseMoveEvent(MouseMoveEvent&) {} - -#ifndef CORRADE_TARGET_EMSCRIPTEN +void Sdl2Application::mouseScrollEvent(MouseScrollEvent&) {} +void Sdl2Application::multiGestureEvent(MultiGestureEvent&) {} void Sdl2Application::textInputEvent(TextInputEvent&) {} void Sdl2Application::textEditingEvent(TextEditingEvent&) {} -#endif Sdl2Application::Configuration::Configuration(): #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_IOS) @@ -499,15 +552,29 @@ Sdl2Application::Configuration::Configuration(): Sdl2Application::Configuration::~Configuration() = default; +std::string Sdl2Application::KeyEvent::keyName(const Key key) { + return SDL_GetKeyName(SDL_Keycode(key)); +} + +std::string Sdl2Application::KeyEvent::keyName() const { + return keyName(_key); +} + Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseEvent::modifiers() { - if(modifiersLoaded) return _modifiers; - modifiersLoaded = true; + if(_modifiersLoaded) return _modifiers; + _modifiersLoaded = true; return _modifiers = fixedModifiers(Uint16(SDL_GetModState())); } Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseMoveEvent::modifiers() { - if(modifiersLoaded) return _modifiers; - modifiersLoaded = true; + if(_modifiersLoaded) return _modifiers; + _modifiersLoaded = true; + return _modifiers = fixedModifiers(Uint16(SDL_GetModState())); +} + +Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseScrollEvent::modifiers() { + if(_modifiersLoaded) return _modifiers; + _modifiersLoaded = true; return _modifiers = fixedModifiers(Uint16(SDL_GetModState())); } diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 7c3c34277..751c478e9 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -331,10 +331,10 @@ class Sdl2Application { class KeyEvent; class MouseEvent; class MouseMoveEvent; - #ifndef CORRADE_TARGET_EMSCRIPTEN + class MouseScrollEvent; + class MultiGestureEvent; class TextInputEvent; class TextEditingEvent; - #endif /** * @brief Default constructor @@ -343,7 +343,8 @@ class Sdl2Application { * * Creates application with default or user-specified configuration. * See @ref Configuration for more information. The program exits if - * the context cannot be created, see below for an alternative. + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit Sdl2Application(const Arguments& arguments, const Configuration& configuration = Configuration()); @@ -421,14 +422,17 @@ class Sdl2Application { /** @{ @name Screen handling */ + #ifndef CORRADE_TARGET_EMSCRIPTEN /** * @brief Window size * * Window size to which all input event coordinates can be related. * Note that especially on HiDPI systems the reported window size might * not be the same as framebuffer size. + * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". */ Vector2i windowSize(); + #endif /** * @brief Swap buffers @@ -583,9 +587,29 @@ class Sdl2Application { */ virtual void mouseMoveEvent(MouseMoveEvent& event); + /** + * @brief Mouse scroll event + * + * Called when a scrolling device is used (mouse wheel or scrolling + * area on a touchpad). Default implementation does nothing. + */ + virtual void mouseScrollEvent(MouseScrollEvent& event); + + /*@}*/ + + /** @{ @name Touch gesture handling */ + + /** + * @brief Multi gesture event + * + * Called when the user performs a gesture using multiple fingers. + * Default implementation does nothing. + * @experimental + */ + virtual void multiGestureEvent(MultiGestureEvent& event); + /*@}*/ - #ifndef CORRADE_TARGET_EMSCRIPTEN /** @{ @name Text input handling */ public: /** @@ -593,30 +617,30 @@ class Sdl2Application { * * If text input is active, text input events go to @ref textInputEvent() * and @ref textEditingEvent(). - * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". + * @note Note that in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" the + * value is emulated and might not reflect external events like + * closing on-screen keyboard. * @see @ref startTextInput(), @ref stopTextInput() */ - bool isTextInputActive() { return SDL_IsTextInputActive(); } + bool isTextInputActive(); /** * @brief Start text input * * Starts text input that will go to @ref textInputEvent() and * @ref textEditingEvent(). - * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". * @see @ref stopTextInput(), @ref isTextInputActive(), * @ref setTextInputRect() */ - void startTextInput() { SDL_StartTextInput(); } + void startTextInput(); /** * @brief Stop text input * - * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". * @see @ref startTextInput(), @ref isTextInputActive(), @ref textInputEvent() * @ref textEditingEvent() */ - void stopTextInput() { SDL_StopTextInput(); } + void stopTextInput(); /** * @brief Set text input rectangle @@ -647,7 +671,6 @@ class Sdl2Application { virtual void textEditingEvent(TextEditingEvent& event); /*@}*/ - #endif private: enum class Flag: UnsignedByte { @@ -675,6 +698,7 @@ class Sdl2Application { UnsignedInt _minimalLoopPeriod; #else SDL_Surface* _glContext; + bool _isTextInputActive = false; #endif std::unique_ptr _context; @@ -869,7 +893,8 @@ class Sdl2Application::Configuration { * backwards-compatible with requested one. Default is * @ref Version::None, i.e. any provided version is used. * @note In @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" this function - * does nothing (@ref Version::GLES200 is always used). + * does nothing (@ref Version::GLES200 or @ref Version::GLES300 is + * used implicitly based on the target). */ Configuration& setVersion(Version version) { #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -946,10 +971,40 @@ class Sdl2Application::InputEvent { * @ref MouseEvent::modifiers(), @ref MouseMoveEvent::modifiers() */ enum class Modifier: Uint16 { - Shift = KMOD_SHIFT, /**< Shift */ - Ctrl = KMOD_CTRL, /**< Ctrl */ - Alt = KMOD_ALT, /**< Alt */ - AltGr = KMOD_MODE, /**< AltGr */ + /** + * Shift + * + * @see @ref KeyEvent::Key::LeftShift, @ref KeyEvent::Key::RightShift + */ + Shift = KMOD_SHIFT, + + /** + * Ctrl + * + * @see @ref KeyEvent::Key::LeftCtrl, @ref KeyEvent::Key::RightCtrl + */ + Ctrl = KMOD_CTRL, + + /** + * Alt + * + * @see @ref KeyEvent::Key::LeftAlt, @ref KeyEvent::Key::RightAlt + */ + Alt = KMOD_ALT, + + /** + * Super key (Windows/⌘) + * + * @see @ref KeyEvent::Key::LeftSuper, @ref KeyEvent::Key::RightSuper + */ + Super = KMOD_GUI, + + /** + * AltGr + * + * @see @ref KeyEvent::Key::AltGr + */ + AltGr = KMOD_MODE, CapsLock = KMOD_CAPS, /**< Caps lock */ NumLock = KMOD_NUM /**< Num lock */ @@ -1016,6 +1071,69 @@ class Sdl2Application::KeyEvent: public Sdl2Application::InputEvent { enum class Key: SDL_Keycode { Unknown = SDLK_UNKNOWN, /**< Unknown key */ + /** + * Left Shift + * + * @see @ref InputEvent::Modifier::Shift + */ + LeftShift = SDLK_LSHIFT, + + /** + * Right Shift + * + * @see @ref InputEvent::Modifier::Shift + */ + RightShift = SDLK_RSHIFT, + + /** + * Left Ctrl + * + * @see @ref InputEvent::Modifier::Ctrl + */ + LeftCtrl = SDLK_LCTRL, + + /** + * Right Ctrl + * + * @see @ref InputEvent::Modifier::Ctrl + */ + RightCtrl = SDLK_RCTRL, + + /** + * Left Alt + * + * @see @ref InputEvent::Modifier::Alt + */ + LeftAlt = SDLK_LALT, + + /** + * Right Alt + * + * @see @ref InputEvent::Modifier::Alt + */ + RightAlt = SDLK_RALT, + + /** + * Left Super key (Windows/⌘) + * + * @see @ref InputEvent::Modifier::Super + */ + LeftSuper = SDLK_LGUI, + + /** + * Right Super key (Windows/⌘) + * + * @see @ref InputEvent::Modifier::Super + */ + RightSuper = SDLK_RGUI, + + /** + * AltGr + * + * @see @ref InputEvent::Modifier::AltGr + */ + AltGr = SDLK_MODE, + Enter = SDLK_RETURN, /**< Enter */ Esc = SDLK_ESCAPE, /**< Escape */ @@ -1094,23 +1212,58 @@ class Sdl2Application::KeyEvent: public Sdl2Application::InputEvent { Z = SDLK_z /**< Letter Z */ }; - /** @brief Key */ + /** + * @brief Name for given key + * + * Human-readable localized UTF-8 name for given @p key, intended for + * displaying to the user in e.g. key binding configuration. If there + * is no name for given key, empty string is returned. + * @see @ref keyName(Key) + */ + static std::string keyName(Key key); + + /** + * @brief Key + * + * @see @ref keyName() + */ constexpr Key key() const { return _key; } + /** + * @brief Key name + * + * Human-readable localized UTF-8 name for the key returned by + * @ref key(), intended for displaying to the user in e.g. + * key binding configuration. If there is no name for that key, empty + * string is returned. + * @see @ref keyName(Key) + */ + std::string keyName() const; + /** @brief Modifiers */ constexpr Modifiers modifiers() const { return _modifiers; } + /** + * @brief Whether the key press is repeated + * + * Returns `true` if the key press event is repeated, `false` if not or + * if this was key release event. + */ + constexpr bool isRepeated() const { return _repeated; } + private: - constexpr KeyEvent(Key key, Modifiers modifiers): _key(key), _modifiers(modifiers) {} + constexpr KeyEvent(Key key, Modifiers modifiers, bool repeated): _key{key}, _modifiers{modifiers}, _repeated{repeated} {} const Key _key; const Modifiers _modifiers; + const bool _repeated; }; /** @brief Mouse event -@see @ref MouseMoveEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() +@see @ref MouseMoveEvent, @ref MouseScrollEvent, @ref mousePressEvent(), + @ref mouseReleaseEvent() */ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent { friend Sdl2Application; @@ -1125,8 +1278,26 @@ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent { Left = SDL_BUTTON_LEFT, /**< Left button */ Middle = SDL_BUTTON_MIDDLE, /**< Middle button */ Right = SDL_BUTTON_RIGHT, /**< Right button */ - WheelUp = SDL_BUTTON_X1, /**< Wheel up */ - WheelDown = SDL_BUTTON_X2 /**< Wheel down */ + + /** First extra button (e.g. wheel left) */ + X1 = SDL_BUTTON_X1, + + /** Second extra button (e.g. wheel right) */ + X2 = SDL_BUTTON_X2, + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * Wheel up + * @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead. + */ + WheelUp CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = SDL_BUTTON_X2 + 1, + + /** + * Wheel down + * @deprecated Use @ref MouseScrollEvent and @ref mouseScrollEvent() instead. + */ + WheelDown CORRADE_DEPRECATED_ENUM("use mouseScrollEvent() and MouseScrollEvent instead") = SDL_BUTTON_X2 + 2 + #endif }; /** @brief Button */ @@ -1135,6 +1306,15 @@ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent { /** @brief Position */ constexpr Vector2i position() const { return _position; } + #ifndef CORRADE_TARGET_EMSCRIPTEN + /** + * @brief Click count + * + * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". + */ + constexpr Int clickCount() const { return _clickCount; } + #endif + /** * @brief Modifiers * @@ -1143,18 +1323,29 @@ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent { Modifiers modifiers(); private: - constexpr MouseEvent(Button button, const Vector2i& position): _button(button), _position(position), modifiersLoaded(false) {} + constexpr MouseEvent(Button button, const Vector2i& position + #ifndef CORRADE_TARGET_EMSCRIPTEN + , Int clickCount + #endif + ): _button{button}, _position{position}, + #ifndef CORRADE_TARGET_EMSCRIPTEN + _clickCount{clickCount}, + #endif + _modifiersLoaded{false} {} const Button _button; const Vector2i _position; - bool modifiersLoaded; + #ifndef CORRADE_TARGET_EMSCRIPTEN + const Int _clickCount; + #endif + bool _modifiersLoaded; Modifiers _modifiers; }; /** @brief Mouse move event -@see @ref MouseEvent, @ref mouseMoveEvent() +@see @ref MouseEvent, @ref MouseScrollEvent, @ref mouseMoveEvent() */ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { friend Sdl2Application; @@ -1169,8 +1360,12 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { Left = SDL_BUTTON_LMASK, /**< Left button */ Middle = SDL_BUTTON_MMASK, /**< Middle button */ Right = SDL_BUTTON_RMASK, /**< Right button */ - WheelUp = SDL_BUTTON_X1MASK, /**< Wheel up */ - WheelDown = SDL_BUTTON_X2MASK /**< Wheel down */ + + /** First extra button (e.g. wheel left) */ + X1 = SDL_BUTTON_X1MASK, + + /** Second extra button (e.g. wheel right) */ + X2 = SDL_BUTTON_X2MASK }; /** @@ -1201,19 +1396,113 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { Modifiers modifiers(); private: - constexpr MouseMoveEvent(const Vector2i& position, const Vector2i& relativePosition, Buttons buttons): _position(position), _relativePosition(relativePosition), modifiersLoaded(false), _buttons(buttons) {} + constexpr MouseMoveEvent(const Vector2i& position, const Vector2i& relativePosition, Buttons buttons): _position{position}, _relativePosition{relativePosition}, _buttons{buttons}, _modifiersLoaded{false} {} const Vector2i _position, _relativePosition; - bool modifiersLoaded; - Buttons _buttons; + const Buttons _buttons; + bool _modifiersLoaded; Modifiers _modifiers; }; -#ifndef CORRADE_TARGET_EMSCRIPTEN +/** +@brief Mouse scroll event + +@see @ref MouseEvent, @ref MouseMoveEvent, @ref mouseScrollEvent() +*/ +class Sdl2Application::MouseScrollEvent: public Sdl2Application::InputEvent { + friend Sdl2Application; + + public: + /** @brief Scroll offset */ + constexpr Vector2 offset() const { return _offset; } + + /** + * @brief Modifiers + * + * Lazily populated on first request. + */ + Modifiers modifiers(); + + private: + constexpr MouseScrollEvent(const Vector2& offset): _offset{offset}, _modifiersLoaded{false} {} + + const Vector2 _offset; + bool _modifiersLoaded; + Modifiers _modifiers; +}; + +/** +@brief Multi gesture event + +@experimental +@see @ref multiGestureEvent() +*/ +class Sdl2Application::MultiGestureEvent { + friend Sdl2Application; + + public: + /** @brief Copying is not allowed */ + MultiGestureEvent(const MultiGestureEvent&) = delete; + + /** @brief Moving is not allowed */ + MultiGestureEvent(MultiGestureEvent&&) = delete; + + /** @brief Copying is not allowed */ + MultiGestureEvent& operator=(const MultiGestureEvent&) = delete; + + /** @brief Moving is not allowed */ + MultiGestureEvent& operator=(MultiGestureEvent&&) = delete; + + /** @brief Whether the event is accepted */ + constexpr bool isAccepted() const { return _accepted; } + + /** + * @brief Set event as accepted + * + * If the event is ignored (i.e., not set as accepted), it might be + * propagated elsewhere, for example 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 Gesture center */ + Vector2 center() const { return _center; } + + /** + * @brief Relative rotation + * + * Rotation relative to previous event. + */ + Float relativeRotation() const { return _relativeRotation; } + + /** + * @brief Relative distance + * + * Distance of the fingers relative to previous event. + */ + Float relativeDistance() const { return _relativeDistance; } + + /** + * @brief Finger count + * + * Count of fingers performing the gesture. + */ + Int fingerCount() const { return _fingerCount; } + + private: + constexpr MultiGestureEvent(const Vector2& center, Float relativeRotation, Float relativeDistance, Int fingerCount): _center{center}, _relativeRotation{relativeRotation}, _relativeDistance{relativeDistance}, _fingerCount{fingerCount}, _accepted{false} {} + + Vector2 _center; + Float _relativeRotation, + _relativeDistance; + Int _fingerCount; + bool _accepted; +}; + /** @brief Text input event -@note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". @see @ref TextEditingEvent, @ref textInputEvent() */ class Sdl2Application::TextInputEvent { @@ -1258,7 +1547,6 @@ class Sdl2Application::TextInputEvent { /** @brief Text editing event -@note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". @see @ref textEditingEvent() */ class Sdl2Application::TextEditingEvent { @@ -1306,7 +1594,6 @@ class Sdl2Application::TextEditingEvent { Int _start, _length; bool _accepted; }; -#endif /** @hideinitializer @brief Entry point for SDL2-based applications diff --git a/src/Magnum/Platform/WindowlessCglApplication.cpp b/src/Magnum/Platform/WindowlessCglApplication.cpp index 49140e99b..b43ae3455 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.cpp +++ b/src/Magnum/Platform/WindowlessCglApplication.cpp @@ -35,25 +35,7 @@ namespace Magnum { namespace Platform { -#ifndef DOXYGEN_GENERATING_OUTPUT -WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments): WindowlessCglApplication{arguments, Configuration{}} {} -#endif - -WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessCglApplication{arguments, nullptr} { - createContext(configuration); -} - -WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, std::nullptr_t): _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} - -void WindowlessCglApplication::createContext() { createContext({}); } - -void WindowlessCglApplication::createContext(const Configuration& configuration) { - if(!tryCreateContext(configuration)) std::exit(1); -} - -bool WindowlessCglApplication::tryCreateContext(const Configuration&) { - CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false); - +WindowlessCglContext::WindowlessCglContext(const Configuration&, Context*) { int formatCount; CGLPixelFormatAttribute attributes32[] = { kCGLPFAAccelerated, @@ -62,7 +44,7 @@ bool WindowlessCglApplication::tryCreateContext(const Configuration&) { CGLPixelFormatAttribute(0) }; if(CGLChoosePixelFormat(attributes32, &_pixelFormat, &formatCount) != kCGLNoError) { - Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot choose pixel format for GL 3.2, falling back to 3.0"; + Warning() << "Platform::WindowlessCglContext: cannot choose pixel format for GL 3.2, falling back to 3.0"; CGLPixelFormatAttribute attributes30[] = { kCGLPFAAccelerated, @@ -71,7 +53,7 @@ bool WindowlessCglApplication::tryCreateContext(const Configuration&) { CGLPixelFormatAttribute(0) }; if(CGLChoosePixelFormat(attributes30, &_pixelFormat, &formatCount) != kCGLNoError) { - Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot choose pixel format for GL 3.0, falling back to 2.1"; + Warning() << "Platform::WindowlessCglContext: cannot choose pixel format for GL 3.0, falling back to 2.1"; CGLPixelFormatAttribute attributes21[] = { kCGLPFAAccelerated, @@ -80,31 +62,68 @@ bool WindowlessCglApplication::tryCreateContext(const Configuration&) { CGLPixelFormatAttribute(0) }; if(CGLChoosePixelFormat(attributes21, &_pixelFormat, &formatCount) != kCGLNoError) { - Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot choose pixel format"; - return false; + Error() << "Platform::WindowlessCglContext: cannot choose pixel format"; + return; } } } - if(CGLCreateContext(_pixelFormat, nullptr, &_glContext) != kCGLNoError) { - Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot create context"; - return false; - } + if(CGLCreateContext(_pixelFormat, nullptr, &_context) != kCGLNoError) + Error() << "Platform::WindowlessCglContext: cannot create context"; +} - if(CGLSetCurrentContext(_glContext) != kCGLNoError) { - Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot make context current"; - return false; - } +WindowlessCglContext::WindowlessCglContext(WindowlessCglContext&& other): _pixelFormat{other._pixelFormat}, _context{other._context} { + other._pixelFormat = {}; + other._context = {}; +} - /* Return true if the initialization succeeds */ - return _context->tryCreate(); +WindowlessCglContext::~WindowlessCglContext() { + if(_context) CGLDestroyContext(_context); + if(_pixelFormat) CGLDestroyPixelFormat(_pixelFormat); } -WindowlessCglApplication::~WindowlessCglApplication() { - _context.reset(); +WindowlessCglContext& WindowlessCglContext::operator=(WindowlessCglContext&& other) { + using std::swap; + swap(other._pixelFormat, _pixelFormat); + swap(other._context, _context); + return *this; +} + +bool WindowlessCglContext::makeCurrent() { + if(CGLSetCurrentContext(_context) == kCGLNoError) + return true; + + Error() << "Platform::WindowlessCglContext::makeCurrent(): cannot make context current"; + return false; +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments): WindowlessCglApplication{arguments, Configuration{}} {} +#endif + +WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessCglApplication{arguments, NoCreate} { + createContext(configuration); +} + +WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} + +WindowlessCglApplication::~WindowlessCglApplication() = default; + +void WindowlessCglApplication::createContext() { createContext({}); } + +void WindowlessCglApplication::createContext(const Configuration& configuration) { + if(!tryCreateContext(configuration)) std::exit(1); +} + +bool WindowlessCglApplication::tryCreateContext(const Configuration& configuration) { + CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false); + + WindowlessCglContext glContext{configuration, _context.get()}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + return false; - CGLDestroyContext(_glContext); - CGLDestroyPixelFormat(_pixelFormat); + _glContext = std::move(glContext); + return true; } }} diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index 374fa864c..9acb76868 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -28,12 +28,13 @@ */ /** @file - * @brief Class @ref Magnum::Platform::WindowlessCglApplication, macro @ref MAGNUM_WINDOWLESSCGLAPPLICATION_MAIN() + * @brief Class @ref Magnum::Platform::WindowlessCglApplication, @ref Magnum::Platform::WindowlessCglContext, macro @ref MAGNUM_WINDOWLESSCGLAPPLICATION_MAIN() */ #include #include "Magnum/OpenGL.h" +#include "Magnum/Tags.h" #include #include #include @@ -44,13 +45,99 @@ namespace Magnum { namespace Platform { /** -@brief Windowless CGL application +@brief Windowless CGL context + +GL context used in @ref WindowlessCglApplication. Does not have any default +framebuffer. It is built if `WITH_WINDOWLESSCGLAPPLICATION` is enabled in +CMake. + +Meant to be used when there is a need to manage (multiple) GL contexts +manually. See @ref platform-windowless-contexts for more information. If no +other application header is included, this class is also aliased to +`Platform::WindowlessGLContext`. +*/ +class WindowlessCglContext { + public: + class Configuration; + + /** + * @brief Constructor + * @param configuration Context configuration + * @param context Optional Magnum context instance constructed + * using @ref NoCreate to manage driver workarounds + * + * If version is not specified in @p configuration, it first tries to + * create core context (OpenGL 3.2+), if that fails, tries OpenGL 3.0+ + * and as a last attempt falls back to compatibility OpenGL 2.1 + * context. + * + * Once the context is created, make it current using @ref makeCurrent() + * and create @ref Platform::Context instance to be able to use Magnum. + * @see @ref isCreated() + */ + explicit WindowlessCglContext(const Configuration& configuration, Context* context = nullptr); + + /** + * @brief Construct without creating the context + * + * Move a instance with created context over to make it usable. + */ + explicit WindowlessCglContext(NoCreateT) {} + + /** @brief Copying is not allowed */ + WindowlessCglContext(const WindowlessCglContext&) = delete; + + /** @brief Move constructor */ + WindowlessCglContext(WindowlessCglContext&& other); + + /** @brief Copying is not allowed */ + WindowlessCglContext& operator=(const WindowlessCglContext&) = delete; + + /** @brief Move assignment */ + WindowlessCglContext& operator=(WindowlessCglContext&& other); + + /** + * @brief Destructor + * + * Destroys the context, if any. + */ + ~WindowlessCglContext(); + + /** @brief Whether the context is created */ + bool isCreated() const { return _context; } + + /** + * @brief Make the context current + * + * Prints error message and returns `false` on failure, otherwise + * returns `true`. + */ + bool makeCurrent(); + + private: + CGLPixelFormatObj _pixelFormat{}; + CGLContextObj _context{}; +}; + +/** +@brief Configuration -Application for offscreen rendering using pure CGL. Does not have any default -framebuffer. +@see @ref WindowlessCglContext(), + @ref WindowlessCglApplication::WindowlessCglApplication(), + @ref WindowlessCglApplication::createContext(), + @ref WindowlessCglApplication::tryCreateContext() +*/ +class WindowlessCglContext::Configuration { + public: + constexpr /*implicit*/ Configuration() {} +}; -This application library is available on desktop OpenGL on OS X. It -is built if `WITH_WINDOWLESSCGLAPPLICATION` is enabled in CMake. +/** +@brief Windowless CGL application + +Application for offscreen rendering using @ref WindowlessCglContext. This +application library is available on desktop OpenGL on OS X. It is built if +`WITH_WINDOWLESSCGLAPPLICATION` is enabled in CMake. ## Bootstrap application @@ -104,9 +191,25 @@ class WindowlessCglApplication { char** argv; /**< @brief Argument values */ }; - class Configuration; + /** + * @brief Configuration + * + * @see @ref WindowlessCglApplication(), @ref createContext(), + * @ref tryCreateContext() + */ + typedef WindowlessCglContext::Configuration Configuration; - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + /** + * @brief Default constructor + * @param arguments Application arguments + * @param configuration Configuration + * + * Creates application with default or user-specified configuration. + * See @ref Configuration for more information. The program exits if + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessCglContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit WindowlessCglApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); #else @@ -115,8 +218,22 @@ class WindowlessCglApplication { explicit WindowlessCglApplication(const Arguments& arguments); #endif - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ - explicit WindowlessCglApplication(const Arguments& arguments, std::nullptr_t); + /** + * @brief Construct without creating the context + * @param arguments Application arguments + * + * Unlike above, the context is not created and must be created later + * with @ref createContext() or @ref tryCreateContext(). + */ + explicit WindowlessCglApplication(const Arguments& arguments, NoCreateT); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief WindowlessCglApplication(const Arguments&, NoCreateT) + * @deprecated Use @ref WindowlessCglApplication(const Arguments&, NoCreateT) instead. + */ + CORRADE_DEPRECATED("use WindowlessCglApplication(const Arguments&, NoCreateT) instead") explicit WindowlessCglApplication(const Arguments& arguments, std::nullptr_t): WindowlessCglApplication{arguments, NoCreate} {} + #endif /** @brief Copying is not allowed */ WindowlessCglApplication(const WindowlessCglApplication&) = delete; @@ -144,7 +261,15 @@ class WindowlessCglApplication { thus this is faster than public pure virtual destructor */ ~WindowlessCglApplication(); - /** @copydoc Sdl2Application::createContext() */ + /** + * @brief Create context with given configuration + * + * Must be called if and only if the context wasn't created by the + * constructor itself. Error message is printed and the program exits + * if the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessCglContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT void createContext(const Configuration& configuration = Configuration()); #else @@ -153,27 +278,19 @@ class WindowlessCglApplication { void createContext(); #endif - /** @copydoc Sdl2Application::tryCreateContext() */ + /** + * @brief Try to create context with given configuration + * + * Unlike @ref createContext() returns `false` if the context cannot be + * created, `true` otherwise. + */ bool tryCreateContext(const Configuration& configuration); private: - CGLContextObj _glContext; - CGLPixelFormatObj _pixelFormat; - + WindowlessCglContext _glContext; std::unique_ptr _context; }; -/** -@brief Configuration - -@see @ref WindowlessCglApplication(), @ref createContext(), - @ref tryCreateContext() -*/ -class WindowlessCglApplication::Configuration { - public: - constexpr /*implicit*/ Configuration() {} -}; - /** @hideinitializer @brief Entry point for windowless CGL application @param className Class name @@ -200,6 +317,7 @@ aliased to `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`. #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN typedef WindowlessCglApplication WindowlessApplication; +typedef WindowlessCglContext WindowlessGLContext; #define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSCGLAPPLICATION_MAIN(className) #else #undef MAGNUM_WINDOWLESSAPPLICATION_MAIN diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 61d61ce22..ca63f7a5e 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -35,30 +35,12 @@ namespace Magnum { namespace Platform { -#ifndef DOXYGEN_GENERATING_OUTPUT -WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments): WindowlessEglApplication{arguments, Configuration{}} {} -#endif - -WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessEglApplication{arguments, nullptr} { - createContext(configuration); -} - -WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments, std::nullptr_t): _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} - -void WindowlessEglApplication::createContext() { createContext({}); } - -void WindowlessEglApplication::createContext(const Configuration& configuration) { - if(!tryCreateContext(configuration)) std::exit(1); -} - -bool WindowlessEglApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessEglApplication::tryCreateContext(): context already created", false); - +WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, Context*) { /* Initialize */ _display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if(!eglInitialize(_display, nullptr, nullptr)) { Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot initialize EGL:" << Implementation::eglErrorString(eglGetError()); - return false; + return; } const EGLenum api = @@ -70,7 +52,7 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati ; if(!eglBindAPI(api)) { Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot bind EGL API:" << Implementation::eglErrorString(eglGetError()); - return false; + return; } /* Choose EGL config */ @@ -87,15 +69,16 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati #endif EGL_NONE }; + EGLConfig config; EGLint configCount; - if(!eglChooseConfig(_display, attribs, &_config, 1, &configCount)) { + if(!eglChooseConfig(_display, attribs, &config, 1, &configCount)) { Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot get EGL visual config:" << Implementation::eglErrorString(eglGetError()); - return false; + return; } if(!configCount) { Error() << "Platform::WindowlessEglApplication::tryCreateContext(): no matching EGL visual config available"; - return false; + return; } const EGLint attributes[] = { @@ -113,25 +96,64 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati EGL_NONE }; - if(!(_glContext = eglCreateContext(_display, _config, EGL_NO_CONTEXT, attributes))) { + if(!(_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, attributes))) { Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); - return false; - } - if(!eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, _glContext)) { - Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot make context current:" << Implementation::eglErrorString(eglGetError()); - return false; + return; } +} - /* Return true if the initialization succeeds */ - return _context->tryCreate(); +WindowlessEglContext::WindowlessEglContext(WindowlessEglContext&& other): _display{other._display}, _context{other._context} { + other._display = {}; + other._context = {}; } -WindowlessEglApplication::~WindowlessEglApplication() { - _context.reset(); +WindowlessEglContext::~WindowlessEglContext() { + if(_context) eglDestroyContext(_display, _context); + if(_display) eglTerminate(_display); +} - eglDestroyContext(_display, _glContext); - eglDestroySurface(_display, EGL_NO_SURFACE); - eglTerminate(_display); +WindowlessEglContext& WindowlessEglContext::operator=(WindowlessEglContext && other) { + using std::swap; + swap(other._display, _display); + swap(other._context, _context); + return *this; } +bool WindowlessEglContext::makeCurrent() { + if(eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, _context)) + return true; + + Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot make context current:" << Implementation::eglErrorString(eglGetError()); + return false; +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments): WindowlessEglApplication{arguments, Configuration{}} {} +#endif + +WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessEglApplication{arguments, NoCreate} { + createContext(configuration); +} + +WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} + +void WindowlessEglApplication::createContext() { createContext({}); } + +void WindowlessEglApplication::createContext(const Configuration& configuration) { + if(!tryCreateContext(configuration)) std::exit(1); +} + +bool WindowlessEglApplication::tryCreateContext(const Configuration& configuration) { + CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessEglApplication::tryCreateContext(): context already created", false); + + WindowlessEglContext glContext{configuration, _context.get()}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + return false; + + _glContext = std::move(glContext); + return true; +} + +WindowlessEglApplication::~WindowlessEglApplication() = default; + }} diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 034e66b0d..1eeb03f25 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Platform::WindowlessEglApplication, macro @ref MAGNUM_WINDOWLESSEGLAPPLICATION_MAIN() + * @brief Class @ref Magnum::Platform::WindowlessEglApplication, @ref Magnum::Platform::WindowlessEglContext, macro @ref MAGNUM_WINDOWLESSEGLAPPLICATION_MAIN() */ #include @@ -41,17 +41,138 @@ #include "Magnum/Magnum.h" #include "Magnum/OpenGL.h" +#include "Magnum/Tags.h" #include "Magnum/Platform/Platform.h" namespace Magnum { namespace Platform { +/** +@brief Windowless EGL context + +GL context using EGL without any windowing system, used in +@ref WindowlessEglApplication. Does not have any default framebuffer. It is +built if `WITH_WINDOWLESSEGLAPPLICATION` is enabled in CMake. + +Meant to be used when there is a need to manage (multiple) GL contexts +manually. See @ref platform-windowless-contexts for more information. If no +other application header is included, this class is also aliased to +`Platform::WindowlessGLContext`. +*/ +class WindowlessEglContext { + public: + class Configuration; + + /** + * @brief Constructor + * @param configuration Context configuration + * @param context Optional Magnum context instance constructed + * using @ref NoCreate to manage driver workarounds + * + * Once the context is created, make it current using @ref makeCurrent() + * and create @ref Platform::Context instance to be able to use Magnum. + * @see @ref isCreated() + */ + explicit WindowlessEglContext(const Configuration& configuration, Context* context = nullptr); + + /** + * @brief Construct without creating the context + * + * Move a instance with created context over to make it usable. + */ + explicit WindowlessEglContext(NoCreateT) {} + + /** @brief Copying is not allowed */ + WindowlessEglContext(const WindowlessEglContext&) = delete; + + /** @brief Move constructor */ + WindowlessEglContext(WindowlessEglContext&& other); + + /** @brief Copying is not allowed */ + WindowlessEglContext& operator=(const WindowlessEglContext&) = delete; + + /** @brief Move assignment */ + WindowlessEglContext& operator=(WindowlessEglContext&& other); + + /** + * @brief Destructor + * + * Destroys the context, if any. + */ + ~WindowlessEglContext(); + + /** @brief Whether the context is created */ + bool isCreated() const { return _context; } + + /** + * @brief Make the context current + * + * Prints error message and returns `false` on failure, otherwise + * returns `true`. + */ + bool makeCurrent(); + + private: + EGLDisplay _display{}; + EGLContext _context{}; +}; + +/** +@brief Configuration + +@see @ref WindowlessEglContext(), + @ref WindowlessEglApplication::WindowlessEglApplication(), + @ref WindowlessEglApplication::createContext(), + @ref WindowlessEglApplication::tryCreateContext() +*/ +class WindowlessEglContext::Configuration { + public: + /** + * @brief Context flag + * + * @see @ref Flags, @ref setFlags(), @ref Context::Flag + */ + enum class Flag: int { + Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR /**< Create debug context */ + }; + + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + typedef Containers::EnumSet Flags; + #else + typedef Containers::EnumSet Flags; + #endif + + constexpr /*implicit*/ Configuration() {} + + /** @brief Context flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. See also @ref Context::flags(). + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + private: + Flags _flags; +}; + /** @brief Windowless EGL application -Application for offscreen rendering using EGL without any windowing system. -Does not have any default framebuffer. Supported mainly on OpenGL ES drivers, -for desktop OpenGL the only driver that supports this configuration is -NVidia >= 355. See other `Windowless*Application` classes for an alternative. +Application for offscreen rendering using @ref WindowlessEglContext. Supported +mainly on OpenGL ES drivers, for desktop OpenGL the only driver that supports +this configuration is NVidia >= 355. See other `Windowless*Application` classes +for an alternative. It is built if `WITH_WINDOWLESSEGLAPPLICATION` is enabled in CMake. @@ -104,9 +225,25 @@ class WindowlessEglApplication { char** argv; /**< @brief Argument values */ }; - class Configuration; + /** + * @brief Configuration + * + * @see @ref WindowlessEglApplication(), @ref createContext(), + * @ref tryCreateContext() + */ + typedef WindowlessEglContext::Configuration Configuration; - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + /** + * @brief Default constructor + * @param arguments Application arguments + * @param configuration Configuration + * + * Creates application with default or user-specified configuration. + * See @ref Configuration for more information. The program exits if + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessEglContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit WindowlessEglApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); #else @@ -115,8 +252,22 @@ class WindowlessEglApplication { explicit WindowlessEglApplication(const Arguments& arguments); #endif - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ - explicit WindowlessEglApplication(const Arguments& arguments, std::nullptr_t); + /** + * @brief Constructor + * @param arguments Application arguments + * + * Unlike above, the context is not created and must be created later + * with @ref createContext() or @ref tryCreateContext(). + */ + explicit WindowlessEglApplication(const Arguments& arguments, NoCreateT); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief WindowlessEglApplication(const Arguments&, NoCreateT) + * @deprecated Use @ref WindowlessEglApplication(const Arguments&, NoCreateT) instead. + */ + CORRADE_DEPRECATED("use WindowlessEglApplication(const Arguments&, NoCreateT) instead") explicit WindowlessEglApplication(const Arguments& arguments, std::nullptr_t): WindowlessEglApplication{arguments, NoCreate} {} + #endif /** @brief Copying is not allowed */ WindowlessEglApplication(const WindowlessEglApplication&) = delete; @@ -144,7 +295,15 @@ class WindowlessEglApplication { thus this is faster than public pure virtual destructor */ ~WindowlessEglApplication(); - /** @copydoc Sdl2Application::createContext() */ + /** + * @brief Create context with given configuration + * + * Must be called if and only if the context wasn't created by the + * constructor itself. Error message is printed and the program exits + * if the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessEglContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT void createContext(const Configuration& configuration = Configuration()); #else @@ -153,63 +312,17 @@ class WindowlessEglApplication { void createContext(); #endif - /** @copydoc Sdl2Application::tryCreateContext() */ - bool tryCreateContext(const Configuration& configuration); - - private: - EGLDisplay _display; - EGLConfig _config; - EGLContext _glContext; - - std::unique_ptr _context; -}; - -/** -@brief Configuration - -@see @ref WindowlessEglApplication(), @ref createContext(), - @ref tryCreateContext() -*/ -class WindowlessEglApplication::Configuration { - public: /** - * @brief Context flag - * - * @see @ref Flags, @ref setFlags(), @ref Context::Flag - */ - enum class Flag: int { - Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR /**< Create debug context */ - }; - - /** - * @brief Context flags + * @brief Try to create context with given configuration * - * @see @ref setFlags(), @ref Context::Flags + * Unlike @ref createContext() returns `false` if the context cannot be + * created, `true` otherwise. */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else - typedef Containers::EnumSet Flags; - #endif - - constexpr /*implicit*/ Configuration() {} - - /** @brief Context flags */ - Flags flags() const { return _flags; } - - /** - * @brief Set context flags - * @return Reference to self (for method chaining) - * - * Default is no flag. See also @ref Context::flags(). - */ - Configuration& setFlags(Flags flags) { - _flags = flags; - return *this; - } + bool tryCreateContext(const Configuration& configuration); private: - Flags _flags; + WindowlessEglContext _glContext; + std::unique_ptr _context; }; /** @hideinitializer @@ -231,6 +344,7 @@ windowless application header is included this macro is also aliased to #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN typedef WindowlessEglApplication WindowlessApplication; +typedef WindowlessEglContext WindowlessGLContext; #define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSEGLAPPLICATION_MAIN(className) #else #undef MAGNUM_WINDOWLESSAPPLICATION_MAIN diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 0e1379eee..9e9a0dc76 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -37,32 +37,15 @@ namespace { enum { None = 0L }; } namespace Magnum { namespace Platform { -#ifndef DOXYGEN_GENERATING_OUTPUT -WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments): WindowlessGlxApplication{arguments, Configuration{}} {} -#endif - -WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, const Configuration& configuration): WindowlessGlxApplication{arguments, nullptr} { - createContext(configuration); -} - -WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, std::nullptr_t): _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} - -void WindowlessGlxApplication::createContext() { createContext({}); } - -void WindowlessGlxApplication::createContext(const Configuration& configuration) { - if(!tryCreateContext(configuration)) std::exit(1); -} - -bool WindowlessGlxApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false); +WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configuration& configuration, Context* const magnumContext) { _display = XOpenDisplay(nullptr); /* Check version */ int major, minor; glXQueryVersion(_display, &major, &minor); if(major == 1 && minor < 4) { - Error() << "Platform::WindowlessGlxApplication::tryCreateContext(): GLX version 1.4 or greater is required"; - return false; + Error() << "Platform::WindowlessGlxContext: GLX version 1.4 or greater is required"; + return; } /* Choose config */ @@ -70,8 +53,8 @@ bool WindowlessGlxApplication::tryCreateContext(const Configuration& configurati constexpr static const int fbAttributes[] = { None }; GLXFBConfig* configs = glXChooseFBConfig(_display, DefaultScreen(_display), fbAttributes, &configCount); if(!configCount) { - Error() << "Platform::WindowlessGlxApplication::tryCreateContext(): no supported framebuffer configuration found"; - return false; + Error() << "Platform::WindowlessGlxContext: no supported framebuffer configuration found"; + return; } /* Create pbuffer */ @@ -82,6 +65,10 @@ bool WindowlessGlxApplication::tryCreateContext(const Configuration& configurati }; _pbuffer = glXCreatePbuffer(_display, configs[0], pbufferAttributes); + /* Get pointer to proper context creation function */ + const PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast(glXGetProcAddress(reinterpret_cast("glXCreateContextAttribsARB"))); + + /* Optimistically choose core context first */ const GLint contextAttributes[] = { #ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES3 @@ -95,8 +82,6 @@ bool WindowlessGlxApplication::tryCreateContext(const Configuration& configurati GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, GLX_CONTEXT_FLAGS_ARB, GLint(configuration.flags()), #else - /* Similarly to what's done in Sdl2Application, try to request core - context first */ GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 1, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, @@ -104,73 +89,124 @@ bool WindowlessGlxApplication::tryCreateContext(const Configuration& configurati #endif 0 }; - - const PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast(glXGetProcAddress(reinterpret_cast("glXCreateContextAttribsARB"))); - _glContext = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, contextAttributes); + _context = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, contextAttributes); #ifndef MAGNUM_TARGET_GLES - /* Fall back to (forward compatible) GL 2.1, if version is not - user-specified and either core context creation fails or we are on - binary NVidia/AMD drivers on Linux/Windows. Instead of creating forward- - compatible context with highest available version, they force the - version to the one specified, which is completely useless behavior. */ - #ifndef CORRADE_TARGET_APPLE - constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; - constexpr static const char amdVendorString[] = "ATI Technologies Inc."; - const char* vendorString; - #endif - if(!_glContext - #ifndef CORRADE_TARGET_APPLE - /* We need to make the context current first, sorry about the UGLY code - and HOPEFULLY THERE WON'T BE MORE WORKAROUNDS */ - || (glXMakeContextCurrent(_display, _pbuffer, _pbuffer, _glContext) && - (vendorString = reinterpret_cast(glGetString(GL_VENDOR)), - (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || - std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && - !_context->isDriverWorkaroundDisabled("amd-nv-no-forward-compatible-core-context"))) - #endif - ) { - /* Don't print any warning when doing the NV workaround, because the - bug will be there probably forever */ - if(!_glContext) Warning() - << "Platform::WindowlessGlxApplication::tryCreateContext(): cannot create core context, falling back to compatibility context"; - else { - glXMakeCurrent(_display, None, nullptr); - glXDestroyContext(_display, _glContext); - } + /* Fall back to (forward compatible) GL 2.1 if core context creation fails */ + if(!_context) { + Warning() << "Platform::WindowlessGlxContext: cannot create core context, falling back to compatibility context"; const GLint fallbackContextAttributes[] = { GLX_CONTEXT_FLAGS_ARB, GLint(configuration.flags()), 0 }; + _context = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, fallbackContextAttributes); + + /* Fall back to (forward compatible) GL 2.1 if we are on binary NVidia/AMD + drivers on Linux. Instead of creating forward-compatible context with + highest available version, they force the version to the one specified, + which is completely useless behavior. */ + } else { + /* We need to make the context current to read out vendor string, so + save the previous values so we can safely revert back without + messing up the state */ + GLXDrawable currentDrawable = glXGetCurrentDrawable(); + GLXDrawable currentReadDrawable = glXGetCurrentReadDrawable(); + GLXContext currentContext = glXGetCurrentContext(); + if(!glXMakeContextCurrent(_display, _pbuffer, _pbuffer, _context)) { + Error() << "Platform::WindowlessGlxContext: cannot make context current"; + return; + } - _glContext = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, fallbackContextAttributes); + /* The workaround check is the last so it doesn't appear in workaround + list on unrelated drivers */ + constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; + constexpr static const char amdVendorString[] = "ATI Technologies Inc."; + const char* const vendorString = reinterpret_cast(glGetString(GL_VENDOR)); + if((std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || + std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && + (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"))) + { + /* Destroy the core context and create a compatibility one */ + glXDestroyContext(_display, _context); + const GLint fallbackContextAttributes[] = { + GLX_CONTEXT_FLAGS_ARB, GLint(configuration.flags()), + 0 + }; + _context = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, fallbackContextAttributes); + } + + /* Revert back the old context */ + if(!glXMakeContextCurrent(_display, currentDrawable, currentReadDrawable, currentContext)) { + Error() << "Platform::WindowlessGlxContext: cannot make the previous context current"; + return; + } } + #else + static_cast(magnumContext); #endif XFree(configs); - if(!_glContext) { - Error() << "Platform::WindowlessGlxApplication::tryCreateContext(): cannot create context"; - return false; - } + if(!_context) + Error() << "Platform::WindowlessGlxContext: cannot create context"; +} - /* Set OpenGL context as current */ - if(!glXMakeContextCurrent(_display, _pbuffer, _pbuffer, _glContext)) { - Error() << "Platform::WindowlessGlxApplication::tryCreateContext(): cannot make context current"; - return false; - } +WindowlessGlxContext::WindowlessGlxContext(WindowlessGlxContext&& other): _display{other._display}, _pbuffer{other._pbuffer}, _context{other._context} { + other._display = {}; + other._context = {}; + other._pbuffer = {}; +} + +WindowlessGlxContext::~WindowlessGlxContext() { + if(_context) glXDestroyContext(_display, _context); + if(_pbuffer) glXDestroyPbuffer(_display, _pbuffer); + if(_display) XCloseDisplay(_display); +} - /* Return true if the initialization succeeds */ - return _context->tryCreate(); +WindowlessGlxContext& WindowlessGlxContext::operator=(WindowlessGlxContext&& other) { + using std::swap; + swap(other._display, _display); + swap(other._pbuffer, _pbuffer); + swap(other._context, _context); + return *this; } -WindowlessGlxApplication::~WindowlessGlxApplication() { - _context.reset(); +bool WindowlessGlxContext::makeCurrent() { + if(glXMakeContextCurrent(_display, _pbuffer, _pbuffer, _context)) + return true; - glXMakeCurrent(_display, None, nullptr); - glXDestroyPbuffer(_display, _pbuffer); - glXDestroyContext(_display, _glContext); + Error() << "Platform::WindowlessGlxContext::makeCurrent(): cannot make context current"; + return false; } +#ifndef DOXYGEN_GENERATING_OUTPUT +WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments): WindowlessGlxApplication{arguments, Configuration{}} {} +#endif + +WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, const Configuration& configuration): WindowlessGlxApplication{arguments, NoCreate} { + createContext(configuration); +} + +WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} + +void WindowlessGlxApplication::createContext() { createContext({}); } + +void WindowlessGlxApplication::createContext(const Configuration& configuration) { + if(!tryCreateContext(configuration)) std::exit(1); +} + +bool WindowlessGlxApplication::tryCreateContext(const Configuration& configuration) { + CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false); + + WindowlessGlxContext glContext{configuration, _context.get()}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + return false; + + _glContext = std::move(glContext); + return true; +} + +WindowlessGlxApplication::~WindowlessGlxApplication() = default; + }} diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index bdc2d9ee2..164204901 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Platform::WindowlessGlxApplication, macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN() + * @brief Class @ref Magnum::Platform::WindowlessGlxApplication, @ref Magnum::Platform::WindowlessGlxContext, macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN() */ #include @@ -43,16 +43,147 @@ #undef Status #include "Magnum/Magnum.h" +#include "Magnum/Tags.h" #include "Magnum/Platform/Platform.h" namespace Magnum { namespace Platform { /** -@brief Windowless GLX application +@brief Windowless GLX context + +GL context using pure X11 and GLX, used in @ref WindowlessGlxApplication. Does +not have any default framebuffer. It is built if `WITH_WINDOWLESSGLXAPPLICATION` +is enabled in CMake. + +Meant to be used when there is a need to manage (multiple) GL contexts +manually. See @ref platform-windowless-contexts for more information. If no +other application header is included, this class is also aliased to +`Platform::WindowlessGLContext`. +*/ +class WindowlessGlxContext { + public: + class Configuration; + + /** + * @brief Constructor + * @param configuration Context configuration + * @param context Optional Magnum context instance constructed + * using @ref NoCreate to manage driver workarounds + * + * On desktop GL, if version is not specified in @p configuration, the + * application first tries to create core context (OpenGL 3.1+) and if + * that fails, falls back to compatibility OpenGL 2.1 context. However, + * on binary AMD and NVidia drivers, creating core context does not use + * the largest available version. If the application detects such case + * (and given workaround is not disabled in optionally passed + * @p context instance), the core context is destroyed and + * compatibility OpenGL 2.1 context is created instead to make the + * driver use the latest available version. + * + * Once the context is created, make it current using @ref makeCurrent() + * and create @ref Platform::Context instance to be able to use Magnum. + * @see @ref isCreated() + */ + explicit WindowlessGlxContext(const Configuration& configuration, Context* context = nullptr); + + /** + * @brief Construct without creating the context + * + * Move a instance with created context over to make it usable. + */ + explicit WindowlessGlxContext(NoCreateT) {} + + /** @brief Copying is not allowed */ + WindowlessGlxContext(const WindowlessGlxContext&) = delete; + + /** @brief Move constructor */ + WindowlessGlxContext(WindowlessGlxContext&& other); + + /** @brief Copying is not allowed */ + WindowlessGlxContext& operator=(const WindowlessGlxContext&) = delete; + + /** @brief Move assignment */ + WindowlessGlxContext& operator=(WindowlessGlxContext&& other); + + /** + * @brief Destructor + * + * Destroys the context, if any. + */ + ~WindowlessGlxContext(); + + /** @brief Whether the context is created */ + bool isCreated() const { return _context; } + + /** + * @brief Make the context current + * + * Prints error message and returns `false` on failure, otherwise + * returns `true`. + */ + bool makeCurrent(); + + private: + Display* _display{}; + GLXPbuffer _pbuffer{}; + GLXContext _context{}; +}; + +/** +@brief Configuration + +@see @ref WindowlessGlxContext(), + @ref WindowlessGlxApplication::WindowlessGlxApplication(), + @ref WindowlessGlxApplication::createContext(), + @ref WindowlessGlxApplication::tryCreateContext() +*/ +class WindowlessGlxContext::Configuration { + public: + /** + * @brief Context flag + * + * @see @ref Flags, @ref setFlags(), @ref Context::Flag + */ + enum class Flag: int { + Debug = GLX_CONTEXT_DEBUG_BIT_ARB /**< Create debug context */ + }; + + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + typedef Containers::EnumSet Flags; + #else + typedef Containers::EnumSet Flags; + #endif + + constexpr /*implicit*/ Configuration() {} + + /** @brief Context flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. See also @ref Context::flags(). + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } -Application for offscreen rendering using pure X11 and GLX. + private: + Flags _flags; +}; -This application library is available on desktop OpenGL and +/** +@brief Windowless GLX application + +Application for offscreen rendering using @ref WindowlessGlxContext. This +application library is available on desktop OpenGL and @ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It depends on **X11** library and is built if `WITH_WINDOWLESSGLXAPPLICATION` is enabled in CMake. @@ -107,9 +238,25 @@ class WindowlessGlxApplication { char** argv; /**< @brief Argument values */ }; - class Configuration; + /** + * @brief Configuration + * + * @see @ref WindowlessGlxApplication(), @ref createContext(), + * @ref tryCreateContext() + */ + typedef WindowlessGlxContext::Configuration Configuration; - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + /** + * @brief Default constructor + * @param arguments Application arguments + * @param configuration Configuration + * + * Creates application with default or user-specified configuration. + * See @ref Configuration for more information. The program exits if + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessGlxContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit WindowlessGlxApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); #else @@ -118,8 +265,22 @@ class WindowlessGlxApplication { explicit WindowlessGlxApplication(const Arguments& arguments); #endif - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ - explicit WindowlessGlxApplication(const Arguments& arguments, std::nullptr_t); + /** + * @brief Constructor + * @param arguments Application arguments + * + * Unlike above, the context is not created and must be created later + * with @ref createContext() or @ref tryCreateContext(). + */ + explicit WindowlessGlxApplication(const Arguments& arguments, NoCreateT); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief WindowlessGlxApplication(const Arguments&, NoCreateT) + * @deprecated Use @ref WindowlessGlxApplication(const Arguments&, NoCreateT) instead. + */ + CORRADE_DEPRECATED("use WindowlessGlxApplication(const Arguments&, NoCreateT) instead") explicit WindowlessGlxApplication(const Arguments& arguments, std::nullptr_t): WindowlessGlxApplication{arguments, NoCreate} {} + #endif /** @brief Copying is not allowed */ WindowlessGlxApplication(const WindowlessGlxApplication&) = delete; @@ -147,7 +308,15 @@ class WindowlessGlxApplication { thus this is faster than public pure virtual destructor */ ~WindowlessGlxApplication(); - /** @copydoc Sdl2Application::createContext() */ + /** + * @brief Create context with given configuration + * + * Must be called if and only if the context wasn't created by the + * constructor itself. Error message is printed and the program exits + * if the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessGlxContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT void createContext(const Configuration& configuration = Configuration()); #else @@ -156,63 +325,17 @@ class WindowlessGlxApplication { void createContext(); #endif - /** @copydoc Sdl2Application::tryCreateContext() */ - bool tryCreateContext(const Configuration& configuration); - - private: - Display* _display; - GLXContext _glContext; - GLXPbuffer _pbuffer; - - std::unique_ptr _context; -}; - -/** -@brief Configuration - -@see @ref WindowlessGlxApplication(), @ref createContext(), - @ref tryCreateContext() -*/ -class WindowlessGlxApplication::Configuration { - public: - /** - * @brief Context flag - * - * @see @ref Flags, @ref setFlags(), @ref Context::Flag - */ - enum class Flag: int { - Debug = GLX_CONTEXT_DEBUG_BIT_ARB /**< Create debug context */ - }; - - /** - * @brief Context flags - * - * @see @ref setFlags(), @ref Context::Flags - */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else - typedef Containers::EnumSet Flags; - #endif - - constexpr /*implicit*/ Configuration() {} - - /** @brief Context flags */ - Flags flags() const { return _flags; } - /** - * @brief Set context flags - * @return Reference to self (for method chaining) + * @brief Try to create context with given configuration * - * Default is no flag. See also @ref Context::flags(). + * Unlike @ref createContext() returns `false` if the context cannot be + * created, `true` otherwise. */ - Configuration& setFlags(Flags flags) { - _flags = flags; - return *this; - } + bool tryCreateContext(const Configuration& configuration); private: - Flags _flags; + WindowlessGlxContext _glContext; + std::unique_ptr _context; }; /** @hideinitializer @@ -241,6 +364,7 @@ aliased to `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`. #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN typedef WindowlessGlxApplication WindowlessApplication; +typedef WindowlessGlxContext WindowlessGLContext; #define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(className) #else #undef MAGNUM_WINDOWLESSAPPLICATION_MAIN diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index aa08accdb..292d06c77 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -3,7 +3,7 @@ /* This file is part of Magnum. - Copyright © 2010, 2011, 2012, 2013, 2014, 2015 + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 Vladimír Vondruš Permission is hereby granted, free of charge, to any person obtaining a @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Platform::WindowlessIosApplication, macro @ref MAGNUM_WINDOWLESSIOSAPPLICATION_MAIN() + * @brief Class @ref Magnum::Platform::WindowlessIosApplication, @ref Magnum::Platform::WindowlessIosContext, macro @ref MAGNUM_WINDOWLESSIOSAPPLICATION_MAIN() */ #include @@ -34,6 +34,7 @@ #include "Magnum/Magnum.h" #include "Magnum/OpenGL.h" +#include "Magnum/Tags.h" #include "Magnum/Platform/Platform.h" #ifdef __OBJC__ @@ -44,12 +45,94 @@ struct EAGLContext; namespace Magnum { namespace Platform { +/** +@brief Windowless iOS context + +GL context using EAGL on iOS, used in @ref WindowlessIosApplication. Does not +have any default framebuffer. It is built if `WITH_WINDOWLESSIOSAPPLICATION` is +enabled in CMake. + +Meant to be used when there is a need to manage (multiple) GL contexts +manually. See @ref platform-windowless-contexts for more information. If no +other application header is included, this class is also aliased to +`Platform::WindowlessGLContext`. +*/ +class WindowlessIosContext { + public: + class Configuration; + + /** + * @brief Constructor + * @param configuration Context configuration + * @param context Optional Magnum context instance constructed + * using @ref NoCreate to manage driver workarounds + * + * Once the context is created, make it current using @ref makeCurrent() + * and create @ref Platform::Context instance to be able to use Magnum. + * @see @ref isCreated() + */ + explicit WindowlessIosContext(const Configuration& configuration, Context* context = nullptr); + + /** + * @brief Construct without creating the context + * + * Move a instance with created context over to make it usable. + */ + explicit WindowlessIosContext(NoCreateT) {} + + /** @brief Copying is not allowed */ + WindowlessIosContext(const WindowlessIosContext&) = delete; + + /** @brief Move constructor */ + WindowlessIosContext(WindowlessIosContext&& other); + + /** @brief Copying is not allowed */ + WindowlessIosContext& operator=(const WindowlessIosContext&) = delete; + + /** @brief Move assignment */ + WindowlessIosContext& operator=(WindowlessIosContext&& other); + + /** + * @brief Destructor + * + * Destroys the context, if any. + */ + ~WindowlessIosContext(); + + /** @brief Whether the context is created */ + bool isCreated() const { return _context; } + + /** + * @brief Make the context current + * + * Prints error message and returns `false` on failure, otherwise + * returns `true`. + */ + bool makeCurrent(); + + private: + EAGLContext* _context{}; +}; + +/** +@brief Configuration + +@see @ref WindowlessIosContext(), + @ref WindowlessIosApplication::WindowlessIosApplication(), + @ref WindowlessIosApplication::createContext(), + @ref WindowlessIosApplication::tryCreateContext() +*/ +class WindowlessIosContext::Configuration { + public: + constexpr /*implicit*/ Configuration() {} +}; + /** @brief Windowless iOS application -Application for offscreen rendering using EAGL on iOS. Does not have any -default framebuffer. It is built if `WITH_WINDOWLESSIOSAPPLICATION` is enabled -in CMake. +Application for offscreen rendering using @ref WindowlessIosContext. Does not +have any default framebuffer. It is built if `WITH_WINDOWLESSIOSAPPLICATION` is +enabled in CMake. ## Bootstrap application @@ -100,9 +183,25 @@ class WindowlessIosApplication { char** argv; /**< @brief Argument values */ }; - class Configuration; + /** + * @brief Configuration + * + * @see @ref WindowlessIosApplication(), @ref createContext(), + * @ref tryCreateContext() + */ + typedef WindowlessIosContext::Configuration Configuration; - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + /** + * @brief Default constructor + * @param arguments Application arguments + * @param configuration Configuration + * + * Creates application with default or user-specified configuration. + * See @ref Configuration for more information. The program exits if + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessIosContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit WindowlessIosApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); #else @@ -111,8 +210,22 @@ class WindowlessIosApplication { explicit WindowlessIosApplication(const Arguments& arguments); #endif - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ - explicit WindowlessIosApplication(const Arguments& arguments, std::nullptr_t); + /** + * @brief Constructor + * @param arguments Application arguments + * + * Unlike above, the context is not created and must be created later + * with @ref createContext() or @ref tryCreateContext(). + */ + explicit WindowlessIosApplication(const Arguments& arguments, NoCreateT); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief WindowlessIosApplication(const Arguments&, NoCreateT) + * @deprecated Use @ref WindowlessIosApplication(const Arguments&, NoCreateT) instead. + */ + CORRADE_DEPRECATED("use WindowlessIosApplication(const Arguments&, NoCreateT) instead") explicit WindowlessIosApplication(const Arguments& arguments, std::nullptr_t): WindowlessIosApplication{arguments, NoCreate} {} + #endif /** @brief Copying is not allowed */ WindowlessIosApplication(const WindowlessIosApplication&) = delete; @@ -140,7 +253,15 @@ class WindowlessIosApplication { thus this is faster than public pure virtual destructor */ ~WindowlessIosApplication(); - /** @copydoc Sdl2Application::createContext() */ + /** + * @brief Create context with given configuration + * + * Must be called if and only if the context wasn't created by the + * constructor itself. Error message is printed and the program exits + * if the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessIosContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT void createContext(const Configuration& configuration = Configuration()); #else @@ -149,55 +270,17 @@ class WindowlessIosApplication { void createContext(); #endif - /** @copydoc Sdl2Application::tryCreateContext() */ - bool tryCreateContext(const Configuration& configuration); - - private: - EAGLContext* _glContext; - - std::unique_ptr _context; -}; - -/** -@brief Configuration - -@see @ref WindowlessIosApplication(), @ref createContext(), - @ref tryCreateContext() -*/ -class WindowlessIosApplication::Configuration { - public: - /** - * @brief Context flag - * - * @see @ref Flags, @ref setFlags(), @ref Context::Flag - */ - enum class Flag: int {}; - - /** - * @brief Context flags - * - * @see @ref setFlags(), @ref Context::Flags - */ - typedef Containers::EnumSet Flags; - - constexpr /*implicit*/ Configuration() {} - - /** @brief Context flags */ - Flags flags() const { return _flags; } - /** - * @brief Set context flags - * @return Reference to self (for method chaining) + * @brief Try to create context with given configuration * - * Default is no flag. See also @ref Context::flags(). + * Unlike @ref createContext() returns `false` if the context cannot be + * created, `true` otherwise. */ - Configuration& setFlags(Flags flags) { - _flags = flags; - return *this; - } + bool tryCreateContext(const Configuration& configuration); private: - Flags _flags; + WindowlessIosContext _glContext; + std::unique_ptr _context; }; /** @hideinitializer @@ -219,6 +302,7 @@ windowless application header is included this macro is also aliased to #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN typedef WindowlessIosApplication WindowlessApplication; +typedef WindowlessIosContext WindowlessGLContext; #define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSIOSAPPLICATION_MAIN(className) #else #undef MAGNUM_WINDOWLESSAPPLICATION_MAIN diff --git a/src/Magnum/Platform/WindowlessIosApplication.mm b/src/Magnum/Platform/WindowlessIosApplication.mm index 921f5d261..172e9273d 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.mm +++ b/src/Magnum/Platform/WindowlessIosApplication.mm @@ -1,7 +1,7 @@ /* This file is part of Magnum. - Copyright © 2010, 2011, 2012, 2013, 2014, 2015 + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 Vladimír Vondruš Permission is hereby granted, free of charge, to any person obtaining a @@ -39,15 +39,50 @@ namespace Magnum { namespace Platform { +WindowlessIosContext::WindowlessIosContext(const Configuration&, Context*) { + if(!(_context = [[EAGLContext alloc] + #ifdef MAGNUM_TARGET_GLES2 + initWithAPI:kEAGLRenderingAPIOpenGLES2 + #else + initWithAPI:kEAGLRenderingAPIOpenGLES3 + #endif + ])) + { + Error() << "Platform::WindowlessIosContext(): cannot create EAGL context"; + } +} + +WindowlessIosContext::WindowlessIosContext(WindowlessIosContext&& other): _context{other._context} { + other._context = {}; +} + +WindowlessIosContext::~WindowlessIosContext() { + if(_context) [_context dealloc]; +} + +WindowlessIosContext& WindowlessIosContext::operator=(WindowlessIosContext&& other) { + using std::swap; + swap(other._context, _context); + return *this; +} + +bool WindowlessIosContext::makeCurrent() { + if([EAGLContext setCurrentContext:_context]) + return true; + + Error() << "Platform::WindowlessIosContext::makeCurrent(): cannot make context current"; + return false; +} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments): WindowlessIosApplication{arguments, Configuration{}} {} #endif -WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments, const Configuration& configuration): WindowlessIosApplication{arguments, nullptr} { +WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments, const Configuration& configuration): WindowlessIosApplication{arguments, NoCreate} { createContext(configuration); } -WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments, std::nullptr_t): _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} +WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} void WindowlessIosApplication::createContext() { createContext({}); } @@ -55,35 +90,17 @@ void WindowlessIosApplication::createContext(const Configuration& configuration) if(!tryCreateContext(configuration)) std::exit(1); } -bool WindowlessIosApplication::tryCreateContext(const Configuration&) { +bool WindowlessIosApplication::tryCreateContext(const Configuration& configuration) { CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessIosApplication::tryCreateContext(): context already created", false); - /* Initialize */ - if(!(_glContext = [[EAGLContext alloc] - #ifdef MAGNUM_TARGET_GLES2 - initWithAPI:kEAGLRenderingAPIOpenGLES2 - #else - initWithAPI:kEAGLRenderingAPIOpenGLES3 - #endif - ])) - { - Error() << "Platform::WindowlessIosApplication::tryCreateContext(): cannot create EAGL context"; - return false; - } - - if(![EAGLContext setCurrentContext:_glContext]) { - Error() << "Platform::WindowlessIosApplication::tryCreateContext(): cannot make context current"; + WindowlessIosContext glContext{configuration, _context.get()}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) return false; - } - /* Return true if the initialization succeeds */ - return _context->tryCreate(); + _glContext = std::move(glContext); + return true; } -WindowlessIosApplication::~WindowlessIosApplication() { - _context.reset(); - - [_glContext dealloc]; -} +WindowlessIosApplication::~WindowlessIosApplication() = default; }} diff --git a/src/Magnum/Platform/WindowlessNaClApplication.cpp b/src/Magnum/Platform/WindowlessNaClApplication.cpp index fd4194d33..440bdd12c 100644 --- a/src/Magnum/Platform/WindowlessNaClApplication.cpp +++ b/src/Magnum/Platform/WindowlessNaClApplication.cpp @@ -34,6 +34,40 @@ namespace Magnum { namespace Platform { +WindowlessNaClContext::WindowlessNaClContext(pp::Instance& instance, const Configuration&, Context*) { + const std::int32_t attributes[] = { + PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, + PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, + PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, + PP_GRAPHICS3DATTRIB_WIDTH, 1, + PP_GRAPHICS3DATTRIB_HEIGHT, 1, + PP_GRAPHICS3DATTRIB_NONE + }; + + std::unique_ptr context{new pp::Graphics3D{*instance, attributes}}; + if(context->is_null()) + Error() << "Platform::WindowlessNaClContext: cannot create context"; + + if(!BindGraphics(*context)) + Error() << "Platform::WindowlessNaClContext: cannot bind graphics"; + + /* All went well, save the context */ + _context = std::move(context); +} + +WindowlessNaClContext::WindowlessNaClContext(WindowlessNaClContext&&) = default; + +WindowlessNaClContext::~WindowlessNaClContext() = default; + +WindowlessNaClContext& WindowlessNaClContext::operator=(WindowlessNaClContext&&) = default; + +bool WindowlessNaClContext::makeCurrent() { + if(!_context) return false; + + glSetCurrentContextPPAPI(_context->pp_resource()); + return true; +} + struct WindowlessNaClApplication::ConsoleDebugOutput { explicit ConsoleDebugOutput(pp::Instance* instance); @@ -55,13 +89,11 @@ WindowlessNaClApplication::WindowlessNaClApplication(const Arguments& arguments) #endif WindowlessNaClApplication::WindowlessNaClApplication(const Arguments& arguments, const Configuration& configuration): -WindowlessNaClApplication{arguments, nullptr} { +WindowlessNaClApplication{arguments, NoCreate} { createContext(configuration); } -WindowlessNaClApplication::WindowlessNaClApplication(const Arguments& arguments, std::nullptr_t): Instance(arguments), Graphics3DClient(this), graphics(nullptr), c(nullptr) { - debugOutput = new ConsoleDebugOutput(this); -} +WindowlessNaClApplication::WindowlessNaClApplication(const Arguments& arguments, NoCreateT): Instance(arguments), Graphics3DClient(this), _glContext{NoCreate}, _debugOutput{new ConsoleDebugOutput{this}} {} void WindowlessNaClApplication::createContext() { createContext({}); } @@ -69,43 +101,18 @@ void WindowlessNaClApplication::createContext(const Configuration& configuration if(!tryCreateContext(configuration)) std::exit(1); } -bool WindowlessNaClApplication::tryCreateContext(const Configuration&) { - CORRADE_ASSERT(!c, "Platform::WindowlessNaClApplication::tryCreateContext(): context already created", false); - - const std::int32_t attributes[] = { - PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, - PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, - PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, - PP_GRAPHICS3DATTRIB_WIDTH, 1, - PP_GRAPHICS3DATTRIB_HEIGHT, 1, - PP_GRAPHICS3DATTRIB_NONE - }; +bool WindowlessNaClApplication::tryCreateContext(const Configuration& configuration) { + CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessNaClApplication::tryCreateContext(): context already created", false); - graphics = new pp::Graphics3D(this, attributes); - if(graphics->is_null()) { - Error() << "Platform::WindowlessNaClApplication::tryCreateContext(): cannot create context"; - delete graphics; - graphics = nullptr; - return false; - } - if(!BindGraphics(*graphics)) { - Error() << "Platform::WindowlessNaClApplication::tryCreateContext(): cannot bind graphics"; - delete graphics; - graphics = nullptr; + WindowlessNaClContext glContext{*this, configuration, _context.get()}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) return false; - } - glSetCurrentContextPPAPI(graphics->pp_resource()); - - /* Return true if the initialization succeeds */ - return c = Platform::Context::tryCreate().release(); + _glContext = std::move(glContext); + return true; } -WindowlessNaClApplication::~WindowlessNaClApplication() { - delete c; - delete graphics; - delete debugOutput; -} +WindowlessNaClApplication::~WindowlessNaClApplication() = default; bool WindowlessNaClApplication::Init(uint32_t , const char* , const char*) { return exec() == 0; diff --git a/src/Magnum/Platform/WindowlessNaClApplication.h b/src/Magnum/Platform/WindowlessNaClApplication.h index 1156a16dd..3bee062c8 100644 --- a/src/Magnum/Platform/WindowlessNaClApplication.h +++ b/src/Magnum/Platform/WindowlessNaClApplication.h @@ -26,9 +26,10 @@ */ /** @file - * @brief Class @ref Magnum::Platform::WindowlessNaClApplication, macro @ref MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() + * @brief Class @ref Magnum::Platform::WindowlessNaClApplication, @ref Magnum::Platform::WindowlessNaClContext, macro @ref MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() */ +#include #include #include @@ -41,6 +42,7 @@ #include #include "Magnum/Magnum.h" +#include "Magnum/Tags.h" #include "Magnum/Platform/Platform.h" namespace pp { @@ -50,13 +52,94 @@ namespace pp { namespace Magnum { namespace Platform { +/** +@brief Windowless NaCl context + +GL context running in [Google Chrome Native Client](https://developers.google.com/native-client/), +used in @ref WindowlessNaClApplication. Does not have any default framebuffer. +It is built if `WITH_WINDOWLESSNACLAPPLICATION` is enabled in CMake. + +Meant to be used when there is a need to manage (multiple) GL contexts +manually. See @ref platform-windowless-contexts for more information. If no +other application header is included, this class is also aliased to +`Platform::WindowlessGLContext`. +*/ +class WindowlessNaClContext { + public: + class Configuration; + + /** + * @brief Constructor + * @param instance Pepper instance handle + * @param configuration Context configuration + * @param context Optional Magnum context instance constructed + * using @ref NoCreate to manage driver workarounds + * + * Once the context is created, make it current using @ref makeCurrent() + * and create @ref Platform::Context instance to be able to use Magnum. + * @see @ref isCreated() + */ + explicit WindowlessNaClContext(pp::Instance& instance, const Configuration& configuration, Context* context = nullptr); + + /** + * @brief Construct without creating the context + * + * Move a instance with created context over to make it usable. + */ + explicit WindowlessNaClContext(NoCreateT) {} + + /** @brief Copying is not allowed */ + WindowlessNaClContext(const WindowlessNaClContext&) = delete; + + /** @brief Move constructor */ + WindowlessNaClContext(WindowlessNaClContext&&); + + /** @brief Copying is not allowed */ + WindowlessNaClContext& operator=(const WindowlessNaClContext&) = delete; + + /** @brief Move assignment */ + WindowlessNaClContext& operator=(WindowlessNaClContext&&); + + /** + * @brief Destructor + * + * Destroys the context, if any. + */ + ~WindowlessNaClContext(); + + /** @brief Whether the context is created */ + bool isCreated() const { return _context; } + + /** + * @brief Make the context current + * + * Prints error message and returns `false` on failure, otherwise + * returns `true`. + */ + bool makeCurrent(); + + private: + std::unique_ptr _context; +}; + +/** +@brief Configuration + +@see @ref WindowlessNaClContext(), + @ref WindowlessNaClApplication::WindowlessNaClApplication(), + @ref WindowlessNaClApplication::createContext(), + @ref WindowlessNaClApplication::tryCreateContext() +*/ +class WindowlessNaClContext::Configuration { + public: + constexpr /*implicit*/ Configuration() {} +}; + /** @nosubgrouping @brief Windowless NaCl application -Application for offscreen rendering running in -[Google Chrome Native Client](https://developers.google.com/native-client/). - -This application library is available only in @ref CORRADE_TARGET_NACL "Native Client", +Application for offscreen rendering using @ref WindowlessNaClContext. This +application library is available only in @ref CORRADE_TARGET_NACL "Native Client", see respective sections in @ref building-corrade-cross-nacl "Corrade's" and @ref building-cross-nacl "Magnum's" building documentation. It is built if `WITH_WINDOWLESSNACLAPPLICATION` is enabled in CMake. @@ -111,9 +194,25 @@ class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClien /** @brief Application arguments */ typedef PP_Instance Arguments; - class Configuration; + /** + * @brief Configuration + * + * @see @ref WindowlessNaClApplication(), @ref createContext(), + * @ref tryCreateContext() + */ + typedef WindowlessNaClContext::Configuration Configuration; - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + /** + * @brief Default constructor + * @param arguments Application arguments + * @param configuration Configuration + * + * Creates application with default or user-specified configuration. + * See @ref Configuration for more information. The program exits if + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessNaClContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit WindowlessNaClApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); #else @@ -122,8 +221,22 @@ class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClien explicit WindowlessNaClApplication(const Arguments& arguments); #endif - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ - explicit WindowlessNaClApplication(const Arguments& arguments, std::nullptr_t); + /** + * @brief Constructor + * @param arguments Application arguments + * + * Unlike above, the context is not created and must be created later + * with @ref createContext() or @ref tryCreateContext(). + */ + explicit WindowlessNaClApplication(const Arguments& arguments, NoCreateT); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief WindowlessNaClApplication(const Arguments&, NoCreateT) + * @deprecated Use @ref WindowlessNaClApplication(const Arguments&, NoCreateT) instead. + */ + CORRADE_DEPRECATED("use WindowlessNaClApplication(const Arguments&, NoCreateT) instead") explicit WindowlessNaClApplication(const Arguments& arguments, std::nullptr_t): WindowlessNaClApplication{arguments, NoCreate} {} + #endif /** @brief Copying is not allowed */ WindowlessNaClApplication(const WindowlessNaClApplication&) = delete; @@ -156,7 +269,15 @@ class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClien thus this is faster than public pure virtual destructor */ ~WindowlessNaClApplication(); - /** @copydoc Sdl2Application::createContext() */ + /** + * @brief Create context with given configuration + * + * Must be called if and only if the context wasn't created by the + * constructor itself. Error message is printed and the program exits + * if the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessNaClContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT void createContext(const Configuration& configuration = Configuration()); #else @@ -165,7 +286,12 @@ class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClien void createContext(); #endif - /** @copydoc Sdl2Application::tryCreateContext() */ + /** + * @brief Try to create context with given configuration + * + * Unlike @ref createContext() returns `false` if the context cannot be + * created, `true` otherwise. + */ bool tryCreateContext(const Configuration& configuration); private: @@ -175,20 +301,9 @@ class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClien bool Init(std::uint32_t, const char*, const char*) override; - pp::Graphics3D* graphics; - Platform::Context* c; - ConsoleDebugOutput* debugOutput; -}; - -/** -@brief Configuration - -@see @ref WindowlessNaClApplication(), @ref createContext(), - @ref tryCreateContext() -*/ -class WindowlessNaClApplication::Configuration { - public: - constexpr /*implicit*/ Configuration() {} + WindowlessNaClContext _glContext; + std::unique_ptr _context; + std::unique_ptr _debugOutput; }; namespace Implementation { @@ -229,6 +344,7 @@ application header is included this macro is also aliased to #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN typedef WindowlessNaClApplication WindowlessApplication; +typedef WindowlessNaClContext WindowlessGLContext; #define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN(className) #else #undef MAGNUM_WINDOWLESSAPPLICATION_MAIN diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 72597d12d..dfea35899 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -25,61 +25,62 @@ #include "WindowlessWglApplication.h" +#include #include #include #include "Magnum/Version.h" #include "Magnum/Platform/Context.h" -namespace Magnum { namespace Platform { - -#ifndef DOXYGEN_GENERATING_OUTPUT -int WindowlessWglApplication::create(LRESULT(CALLBACK windowProcedure)(HWND, UINT, WPARAM, LPARAM)) { - const WNDCLASS wc{ - 0, - windowProcedure, - 0, - 0, - GetModuleHandle(nullptr), - nullptr, - nullptr, - HBRUSH(COLOR_BACKGROUND), - nullptr, - L"Magnum Windowless Application" - }; - if(!RegisterClass(&wc)) return 1; - - CreateWindowW(wc.lpszClassName, L"Magnum Windowless Application", - WS_OVERLAPPEDWINDOW, 0, 0, 32, 32, 0, 0, wc.hInstance, 0); - - /* Hammer the return code out of the messaging thingy */ - MSG msg; - do {} while(GetMessageW(&msg, nullptr, 0, 0) != 0); - return msg.wParam; -} -#endif - #ifndef DOXYGEN_GENERATING_OUTPUT -WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments): WindowlessWglApplication{arguments, Configuration{}} {} +/* Define stuff that we need because I can't be bothered with creating a new + header just for a few defines */ +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 #endif -WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessWglApplication{arguments, nullptr} { - createContext(configuration); -} +namespace Magnum { namespace Platform { -WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, std::nullptr_t): _window(arguments.window), _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} +WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, Context* const magnumContext) { + /* Register the window class (if not yet done) */ + WNDCLASSW wc; + if(!GetClassInfoW(GetModuleHandleW(nullptr), L"Magnum Windowless Application", &wc)) { + wc = WNDCLASSW{ + 0, + DefWindowProcW, + 0, + 0, + GetModuleHandleW(nullptr), + nullptr, + nullptr, + HBRUSH(COLOR_BACKGROUND), + nullptr, + L"Magnum Windowless Application" + }; -void WindowlessWglApplication::createContext() { createContext({}); } - -void WindowlessWglApplication::createContext(const Configuration& configuration) { - if(!tryCreateContext(configuration)) std::exit(1); -} + if(!RegisterClassW(&wc)) { + Error() << "Platform::WindowlessWglContext: cannot create window class:" << GetLastError(); + return; + } + } -bool WindowlessWglApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false); + /* Create the window */ + _window = CreateWindowW(wc.lpszClassName, L"Magnum Windowless Application", + WS_OVERLAPPEDWINDOW, 0, 0, 32, 32, 0, 0, wc.hInstance, 0); - /* Get device context */ + /* Get device context from the newly created window and save the previous + one. In case the previous one is null, wglMakeCurrent(null, ...) would + fail and thus we need to pass at least something there. As a commenter + on https://github.com/glfw/glfw/issues/245#issuecomment-43475120 said: + the Windows API is horrible. HORRIBLE. */ + HDC currentDeviceContext = wglGetCurrentDC(); _deviceContext = GetDC(_window); + if(!currentDeviceContext) currentDeviceContext = _deviceContext; /* Use first provided pixel format */ constexpr static const PIXELFORMATDESCRIPTOR pfd = { @@ -104,49 +105,162 @@ bool WindowlessWglApplication::tryCreateContext(const Configuration& configurati const int pixelFormat = ChoosePixelFormat(_deviceContext, &pfd); SetPixelFormat(_deviceContext, pixelFormat, &pfd); - const int attributes[] = { - WGL_CONTEXT_FLAGS_ARB, int(configuration.flags()), - 0 - }; - /* Create temporary context so we are able to get the pointer to - wglCreateContextAttribsARB() */ - HGLRC temporaryContext = wglCreateContext(_deviceContext); + wglCreateContextAttribsARB(). To avoid messing up the app state we need + to save the old active context and then restore it later. */ + const HGLRC currentContext = wglGetCurrentContext(); + const HGLRC temporaryContext = wglCreateContext(_deviceContext); if(!wglMakeCurrent(_deviceContext, temporaryContext)) { - Error() << "Platform::WindowlessWglApplication::tryCreateContext(): cannot make temporary context current:" << GetLastError(); - return false; + Error() << "Platform::WindowlessWglContext: cannot make temporary context current:" << GetLastError(); + wglDeleteContext(temporaryContext); + return; } - /* Get pointer to proper context creation function and create real context - with it */ + /* Get pointer to proper context creation function */ typedef HGLRC(WINAPI*PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*); const PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast( wglGetProcAddress(reinterpret_cast("wglCreateContextAttribsARB"))); - _renderingContext = wglCreateContextAttribsARB(_deviceContext, nullptr, attributes); - /* Delete the temporary context */ - wglMakeCurrent(_deviceContext, nullptr); - wglDeleteContext(temporaryContext); + /* Optimistically choose core context first */ + const GLint contextAttributes[] = { + #ifdef MAGNUM_TARGET_GLES + #ifdef MAGNUM_TARGET_GLES3 + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + #elif defined(MAGNUM_TARGET_GLES2) + WGL_CONTEXT_MAJOR_VERSION_ARB, 2, + #else + #error unsupported OpenGL ES version + #endif + WGL_CONTEXT_MINOR_VERSION_ARB, 0, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT, + WGL_CONTEXT_FLAGS_ARB, GLint(configuration.flags()), + #else + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + WGL_CONTEXT_MINOR_VERSION_ARB, 1, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB|GLint(configuration.flags()), + #endif + 0 + }; + _context = wglCreateContextAttribsARB(_deviceContext, nullptr, contextAttributes); - if(!_renderingContext) { - Error() << "Platform::WindowlessWglApplication::tryCreateContext(): cannot create context:" << GetLastError(); - return false; + #ifndef MAGNUM_TARGET_GLES + /* Fall back to (forward compatible) GL 2.1 if core context creation fails */ + if(!_context) { + Warning() << "Platform::WindowlessWglContext: cannot create core context, falling back to compatibility context:" << GetLastError(); + + const int fallbackContextAttributes[] = { + WGL_CONTEXT_FLAGS_ARB, int(configuration.flags()), + 0 + }; + _context = wglCreateContextAttribsARB(_deviceContext, nullptr, fallbackContextAttributes); + + /* Fall back to (forward compatible) GL 2.1 if we are on binary + NVidia/AMD/Intel drivers on Windows. Instead of creating forward-compatible + context with highest available version, they force the version to the + one specified, which is completely useless behavior. */ + } else { + /* We need to make the context current to read out vendor string */ + if(!wglMakeCurrent(_deviceContext, _context)) { + Error() << "Platform::WindowlessWglContext: cannot make context current:" << GetLastError(); + + /* Everything failed, at least try to delete the dangling contexts + and revert to the previous context to regain some sanity */ + wglMakeCurrent(_deviceContext, currentContext); + wglDeleteContext(temporaryContext); + return; + } + + /* The workaround check is the last so it doesn't appear in workaround + list on unrelated drivers */ + constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; + constexpr static const char intelVendorString[] = "Intel"; + constexpr static const char amdVendorString[] = "ATI Technologies Inc."; + const char* const vendorString = reinterpret_cast(glGetString(GL_VENDOR)); + if((std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || + std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || + std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && + (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"))) + { + /* Destroy the core context and create a compatibility one */ + wglDeleteContext(_context); + const int fallbackContextAttributes[] = { + WGL_CONTEXT_FLAGS_ARB, int(configuration.flags()), + 0 + }; + _context = wglCreateContextAttribsARB(_deviceContext, nullptr, fallbackContextAttributes); + } } + #endif - /* Set OpenGL context as current */ - if(!wglMakeCurrent(_deviceContext, _renderingContext)) { - Error() << "Platform::WindowlessWglApplication::tryCreateContext(): cannot make context current:" << GetLastError(); - return false; + /* Make the previous context active and delete the temporary context */ + if(!wglMakeCurrent(currentDeviceContext, currentContext)) { + Error() << "Platform::WindowlessWglContext: cannot make the previous context current:" << GetLastError(); + + /* Everything is fucked up, but try to delete the temporary context + anyway */ + wglDeleteContext(temporaryContext); + return; } + wglDeleteContext(temporaryContext); + + if(!_context) + Error() << "Platform::WindowlessWglContext: cannot create context:" << GetLastError(); +} + +WindowlessWglContext::WindowlessWglContext(WindowlessWglContext&& other): _window{other._window}, _deviceContext{other._deviceContext}, _context{other._context} { + other._window = {}; + other._deviceContext = {}; + other._context = {}; +} + +WindowlessWglContext::~WindowlessWglContext() { + if(_context) wglDeleteContext(_context); + if(_window) DestroyWindow(_window); +} + +WindowlessWglContext& WindowlessWglContext::operator=(WindowlessWglContext&& other) { + using std::swap; + swap(other._window, _window); + swap(other._deviceContext, _deviceContext); + swap(other._context, _context); + return *this; +} + +bool WindowlessWglContext::makeCurrent() { + if(wglMakeCurrent(_deviceContext, _context)) + return true; + + Error() << "Platform::WindowlessWglContext::makeCurrent(): cannot make context current:" << GetLastError(); + return false; +} - /* Return true if the initialization succeeds */ - return _context->tryCreate(); +#ifndef DOXYGEN_GENERATING_OUTPUT +WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments): WindowlessWglApplication{arguments, Configuration{}} {} +#endif + +WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessWglApplication{arguments, NoCreate} { + createContext(configuration); } -WindowlessWglApplication::~WindowlessWglApplication() { - _context.reset(); +WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} - wglMakeCurrent(_deviceContext, nullptr); - wglDeleteContext(_renderingContext); +void WindowlessWglApplication::createContext() { createContext({}); } + +void WindowlessWglApplication::createContext(const Configuration& configuration) { + if(!tryCreateContext(configuration)) std::exit(1); } +bool WindowlessWglApplication::tryCreateContext(const Configuration& configuration) { + CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false); + + WindowlessWglContext glContext{configuration, _context.get()}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + return false; + + _glContext = std::move(glContext); + return true; +} + +WindowlessWglApplication::~WindowlessWglApplication() = default; + }} diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index d5cfd2545..e8170ab9d 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Platform::WindowlessWglApplication, macro @ref MAGNUM_WINDOWLESSWGLAPPLICATION_MAIN() + * @brief Class @ref Magnum::Platform::WindowlessWglApplication, @ref Magnum::Platform::WindowlessWglContext, macro @ref MAGNUM_WINDOWLESSWGLAPPLICATION_MAIN() */ #include @@ -39,24 +39,153 @@ #include "Magnum/Magnum.h" #include "Magnum/OpenGL.h" +#include "Magnum/Tags.h" #include "Magnum/Platform/Platform.h" #ifndef DOXYGEN_GENERATING_OUTPUT /* Define stuff that we need because I can't be bothered with creating a new - header just for two defines */ -#define WGL_CONTEXT_FLAGS_ARB 0x2094 + header just for a few defines */ #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 #endif namespace Magnum { namespace Platform { /** -@brief Windowless WGL application +@brief Windowless WGL context + +GL context using pure WINAPI, used in @ref WindowlessWglApplication. It is +built if `WITH_WINDOWLESSWGLAPPLICATION` is enabled in CMake. + +Meant to be used when there is a need to manage (multiple) GL contexts +manually. See @ref platform-windowless-contexts for more information. If no +other application header is included, this class is also aliased to +`Platform::WindowlessGLContext`. +*/ +class WindowlessWglContext { + public: + class Configuration; + + /** + * @brief Constructor + * @param configuration Context configuration + * @param context Optional Magnum context instance constructed + * using @ref NoCreate to manage driver workarounds + * + * On desktop GL, if version is not specified in @p configuration, the + * application first tries to create core context (OpenGL 3.1+) and if + * that fails, falls back to compatibility OpenGL 2.1 context. However, + * on binary AMD and NVidia drivers, creating core context does not use + * the largest available version. If the application detects such case + * (and given workaround is not disabled in optionally passed + * @p context instance), the core context is destroyed and + * compatibility OpenGL 2.1 context is created instead to make the + * driver use the latest available version. + * + * Once the context is created, make it current using @ref makeCurrent() + * and create @ref Platform::Context instance to be able to use Magnum. + * @see @ref isCreated() + */ + explicit WindowlessWglContext(const Configuration& configuration, Context* context = nullptr); + + /** + * @brief Construct without creating the context + * + * Move a instance with created context over to make it usable. + */ + explicit WindowlessWglContext(NoCreateT) {} + + /** @brief Copying is not allowed */ + WindowlessWglContext(const WindowlessWglContext&) = delete; + + /** @brief Move constructor */ + WindowlessWglContext(WindowlessWglContext&& other); + + /** @brief Copying is not allowed */ + WindowlessWglContext& operator=(const WindowlessWglContext&) = delete; + + /** @brief Move assignment */ + WindowlessWglContext& operator=(WindowlessWglContext&& other); + + /** + * @brief Destructor + * + * Destroys the context, if any. + */ + ~WindowlessWglContext(); + + /** @brief Whether the context is created */ + bool isCreated() const { return _context; } + + /** + * @brief Make the context current + * + * Prints error message and returns `false` on failure, otherwise + * returns `true`. + */ + bool makeCurrent(); + + private: + HWND _window{}; + HDC _deviceContext{}; + HGLRC _context{}; +}; + +/** +@brief Configuration + +@see @ref WindowlessWglContext(), + @ref WindowlessWglApplication::WindowlessWglApplication(), + @ref WindowlessWglApplication::createContext(), + @ref WindowlessWglApplication::tryCreateContext() +*/ +class WindowlessWglContext::Configuration { + public: + /** + * @brief Context flag + * + * @see @ref Flags, @ref setFlags(), @ref Context::Flag + */ + enum class Flag: int { + Debug = WGL_CONTEXT_DEBUG_BIT_ARB /**< Create debug context */ + }; -Application for offscreen rendering using pure WINAPI. + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + typedef Containers::EnumSet Flags; + #else + typedef Containers::EnumSet Flags; + #endif + + constexpr /*implicit*/ Configuration() {} -This application library is available on desktop OpenGL on Windows. It is built -if `WITH_WINDOWLESSWGLAPPLICATION` is enabled in CMake. + /** @brief Context flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. See also @ref Context::flags(). + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + private: + Flags _flags; +}; + +/** +@brief Windowless WGL application + +Application for offscreen rendering using @ref WindowlessWglContext. This +application library is available on desktop OpenGL on Windows. It is built if +`WITH_WINDOWLESSWGLAPPLICATION` is enabled in CMake. ## Bootstrap application @@ -102,22 +231,31 @@ class WindowlessWglApplication { /** @brief Application arguments */ struct Arguments { /** @brief Constructor */ - /*implicit*/ constexpr Arguments(int& argc, char** argv, HWND window) noexcept: argc{argc}, argv{argv}, window{window} {} + /*implicit*/ constexpr Arguments(int& argc, char** argv) noexcept: argc{argc}, argv{argv} {} int& argc; /**< @brief Argument count */ char** argv; /**< @brief Argument values */ - #ifndef DOXYGEN_GENERATING_OUTPUT - HWND window; - #endif }; - class Configuration; - - #ifndef DOXYGEN_GENERATING_OUTPUT - static int create(LRESULT(CALLBACK windowProcedure)(HWND, UINT, WPARAM, LPARAM)); - #endif + /** + * @brief Configuration + * + * @see @ref WindowlessWglApplication(), @ref createContext(), + * @ref tryCreateContext() + */ + typedef WindowlessWglContext::Configuration Configuration; - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + /** + * @brief Default constructor + * @param arguments Application arguments + * @param configuration Configuration + * + * Creates application with default or user-specified configuration. + * See @ref Configuration for more information. The program exits if + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessWglContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit WindowlessWglApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); #else @@ -126,8 +264,22 @@ class WindowlessWglApplication { explicit WindowlessWglApplication(const Arguments& arguments); #endif - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ - explicit WindowlessWglApplication(const Arguments& arguments, std::nullptr_t); + /** + * @brief Constructor + * @param arguments Application arguments + * + * Unlike above, the context is not created and must be created later + * with @ref createContext() or @ref tryCreateContext(). + */ + explicit WindowlessWglApplication(const Arguments& arguments, NoCreateT); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief WindowlessWglApplication(const Arguments&, NoCreateT) + * @deprecated Use @ref WindowlessWglApplication(const Arguments&, NoCreateT) instead. + */ + CORRADE_DEPRECATED("use WindowlessWglApplication(const Arguments&, NoCreateT) instead") explicit WindowlessWglApplication(const Arguments& arguments, std::nullptr_t): WindowlessWglApplication{arguments, NoCreate} {} + #endif /** @brief Copying is not allowed */ WindowlessWglApplication(const WindowlessWglApplication&) = delete; @@ -155,7 +307,15 @@ class WindowlessWglApplication { thus this is faster than public pure virtual destructor */ ~WindowlessWglApplication(); - /** @copydoc Sdl2Application::createContext() */ + /** + * @brief Create context with given configuration + * + * Must be called if and only if the context wasn't created by the + * constructor itself. Error message is printed and the program exits + * if the context cannot be created, see @ref tryCreateContext() for an + * alternative. + * @see @ref WindowlessWglContext + */ #ifdef DOXYGEN_GENERATING_OUTPUT void createContext(const Configuration& configuration = Configuration()); #else @@ -164,63 +324,17 @@ class WindowlessWglApplication { void createContext(); #endif - /** @copydoc Sdl2Application::tryCreateContext() */ - bool tryCreateContext(const Configuration& configuration); - - private: - HWND _window; - HDC _deviceContext; - HGLRC _renderingContext; - - std::unique_ptr _context; -}; - -/** -@brief Configuration - -@see @ref WindowlessWglApplication(), @ref createContext(), - @ref tryCreateContext() -*/ -class WindowlessWglApplication::Configuration { - public: - /** - * @brief Context flag - * - * @see @ref Flags, @ref setFlags(), @ref Context::Flag - */ - enum class Flag: int { - Debug = WGL_CONTEXT_DEBUG_BIT_ARB /**< Create debug context */ - }; - - /** - * @brief Context flags - * - * @see @ref setFlags(), @ref Context::Flags - */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else - typedef Containers::EnumSet Flags; - #endif - - constexpr /*implicit*/ Configuration() {} - - /** @brief Context flags */ - Flags flags() const { return _flags; } - /** - * @brief Set context flags - * @return Reference to self (for method chaining) + * @brief Try to create context with given configuration * - * Default is no flag. See also @ref Context::flags(). + * Unlike @ref createContext() returns `false` if the context cannot be + * created, `true` otherwise. */ - Configuration& setFlags(Flags flags) { - _flags = flags; - return *this; - } + bool tryCreateContext(const Configuration& configuration); private: - Flags _flags; + WindowlessWglContext _glContext; + std::unique_ptr _context; }; /** @hideinitializer @@ -234,29 +348,15 @@ windowless application header is included this macro is also aliased to `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`. */ #define MAGNUM_WINDOWLESSWGLAPPLICATION_MAIN(className) \ - int globalArgc; char** globalArgv; \ - LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); \ - LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { \ - switch(message) { \ - case WM_CREATE: \ - { \ - className app({globalArgc, globalArgv, hWnd}); \ - PostQuitMessage(app.exec()); \ - } \ - break; \ - default: return DefWindowProc(hWnd, message, wParam, lParam); \ - } \ - return 0; \ - } \ int main(int argc, char** argv) { \ - globalArgc = argc; \ - globalArgv = argv; \ - return Magnum::Platform::WindowlessWglApplication::create(windowProcedure); \ + className app({argc, argv}); \ + return app.exec(); \ } #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN typedef WindowlessWglApplication WindowlessApplication; +typedef WindowlessWglContext WindowlessGLContext; #define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSWGLAPPLICATION_MAIN(className) #else #undef MAGNUM_WINDOWLESSAPPLICATION_MAIN diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 432274a8f..137959aa9 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -35,51 +35,33 @@ namespace Magnum { namespace Platform { -#ifndef DOXYGEN_GENERATING_OUTPUT -int WindowlessWindowsEglApplication::create(LRESULT(CALLBACK windowProcedure)(HWND, UINT, WPARAM, LPARAM)) { - const WNDCLASS wc{ - 0, - windowProcedure, - 0, - 0, - GetModuleHandle(nullptr), - nullptr, - nullptr, - HBRUSH(COLOR_BACKGROUND), - nullptr, - L"Magnum Windowless Application" - }; - if(!RegisterClass(&wc)) return 1; +WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& configuration, Context*) { + /* Register the window class (if not yet done) */ + WNDCLASSW wc; + if(!GetClassInfoW(GetModuleHandleW(nullptr), L"Magnum Windowless Application", &wc)) { + wc = WNDCLASSW{ + 0, + DefWindowProcW, + 0, + 0, + GetModuleHandleW(nullptr), + nullptr, + nullptr, + HBRUSH(COLOR_BACKGROUND), + nullptr, + L"Magnum Windowless Application" + }; + + if(!RegisterClassW(&wc)) { + Error() << "Platform::WindowlessWglContext: cannot create window class:" << GetLastError(); + return; + } + } - CreateWindowW(wc.lpszClassName, L"Magnum Windowless Application", + /* Create the window */ + _window = CreateWindowW(wc.lpszClassName, L"Magnum Windowless Application", WS_OVERLAPPEDWINDOW, 0, 0, 32, 32, 0, 0, wc.hInstance, 0); - /* Hammer the return code out of the messaging thingy */ - MSG msg; - do {} while(GetMessageW(&msg, nullptr, 0, 0) != 0); - return msg.wParam; -} -#endif - -#ifndef DOXYGEN_GENERATING_OUTPUT -WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments): WindowlessWindowsEglApplication{arguments, Configuration{}} {} -#endif - -WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessWindowsEglApplication{arguments, nullptr} { - createContext(configuration); -} - -WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, std::nullptr_t): _window(arguments.window), _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} - -void WindowlessWindowsEglApplication::createContext() { createContext({}); } - -void WindowlessWindowsEglApplication::createContext(const Configuration& configuration) { - if(!tryCreateContext(configuration)) std::exit(1); -} - -bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false); - /* Initialize */ _display = eglGetDisplay(GetDC(_window)); if(!eglInitialize(_display, nullptr, nullptr)) { @@ -117,7 +99,8 @@ bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& conf EGL_NONE }; EGLint configCount; - if(!eglChooseConfig(_display, attribs, &_config, 1, &configCount)) { + EGLConfig config; + if(!eglChooseConfig(_display, attribs, &config, 1, &configCount)) { Error() << "Platform::WindowlessWindowsEglApplication::tryCreateContext(): cannot get EGL visual config:" << Implementation::eglErrorString(eglGetError()); return false; } @@ -142,30 +125,73 @@ bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& conf EGL_NONE }; - if(!(_glContext = eglCreateContext(_display, _config, EGL_NO_CONTEXT, attributes))) { - Error() << "Platform::WindowlessWindowsEglApplication::tryCreateContext(): cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); - return false; - } - if(!(_surface = eglCreateWindowSurface(_display, _config, _window, nullptr))) { - Error() << "Platform::WindowlessWindowsEglApplication::tryCreateContext(): cannot create window surface:" << Implementation::eglErrorString(eglGetError()); - return false; + if(!(_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, attributes))) { + Error() << "Platform::WindowlessWindowsEglContext: cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); + return; } - if(!eglMakeCurrent(_display, _surface, _surface, _glContext)) { - Error() << "Platform::WindowlessWindowsEglApplication::tryCreateContext(): cannot make context current:" << Implementation::eglErrorString(eglGetError()); - return false; - } + if(!(_surface = eglCreateWindowSurface(_display, config, _window, nullptr))) + Error() << "Platform::WindowlessWindowsEglContext: cannot create window surface:" << Implementation::eglErrorString(eglGetError()); +} + +WindowlessWindowsEglContext::WindowlessWindowsEglContext(WindowlessWindowsEglContext&& other): _window{other._window}, _display{other._display}, _surface{other._surface}, _context{other._context} { + other._window = {}; + other._display = {}; + other._surface = {}; + other._context = {}; +} + +WindowlessWindowsEglContext::~WindowlessWindowsEglContext() { + if(_context) eglDestroyContext(_display, _context); + if(_surface) eglDestroySurface(_display, _surface); + if(_display) eglTerminate(_display); + if(_window) DestroyWindow(_window); +} + +WindowlessWindowsEglContext& WindowlessWindowsEglContext::operator=(WindowlessWindowsEglContext&& other) { + using std::swap; + swap(other._window, _window); + swap(other._display, _display); + swap(other._surface, _surface); + swap(other._context, _context); + return *this; +} - /* Return true if the initialization succeeds */ - return _context->tryCreate(); +bool WindowlessWindowsEglContext::makeCurrent() { + if(eglMakeCurrent(_display, _surface, _surface, _context)) + return true; + + Error() << "Platform::WindowlessWindowsEglContext::makeCurrent(): cannot make context current:" << GetLastError(); + return false; } -WindowlessWindowsEglApplication::~WindowlessWindowsEglApplication() { - _context.reset(); +#ifndef DOXYGEN_GENERATING_OUTPUT +WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments): WindowlessWindowsEglApplication{arguments, Configuration{}} {} +#endif - eglDestroyContext(_display, _glContext); - eglDestroySurface(_display, _surface); - eglTerminate(_display); +WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, const Configuration& configuration): WindowlessWindowsEglApplication{arguments, NoCreate} { + createContext(configuration); } +WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, std::nullptr_t): _glContext{NoCreate}, _context{new Context{NoCreate, arguments.argc, arguments.argv}} {} + +void WindowlessWindowsEglApplication::createContext() { createContext({}); } + +void WindowlessWindowsEglApplication::createContext(const Configuration& configuration) { + if(!tryCreateContext(configuration)) std::exit(1); +} + +bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& configuration) { + CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false); + + WindowlessWindowsEglContext glContext{configuration, _context.get()}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + return false; + + _glContext = std::move(glContext); + return true; +} + +WindowlessWindowsEglApplication::~WindowlessWindowsEglApplication() = default; + }} diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 3910d8be1..07a028458 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Platform::WindowlessWindowsEglApplication, macro @ref MAGNUM_WINDOWLESSWINDOWSEGLAPPLICATION_MAIN() + * @brief Class @ref Magnum::Platform::WindowlessWindowsEglApplication, @ref Magnum::Platform::WindowlessWindowsEglContext, macro @ref MAGNUM_WINDOWLESSWINDOWSEGLAPPLICATION_MAIN() */ #include @@ -41,15 +41,136 @@ #include "Magnum/Magnum.h" #include "Magnum/OpenGL.h" +#include "Magnum/Tags.h" #include "Magnum/Platform/Platform.h" namespace Magnum { namespace Platform { /** -@brief Windowless Windows/EGL application +@brief Windowless Windows/EGL context + +GL context using pure WINAPI and EGL, used in @ref WindowlessWindowsEglApplication. +It is built if `WITH_WINDOWLESSWINDOWSEGLAPPLICATION` is enabled in CMake. + +Meant to be used when there is a need to manage (multiple) GL contexts +manually. See @ref platform-windowless-contexts for more information. If no +other application header is included, this class is also aliased to +`Platform::WindowlessGLContext`. +*/ +class WindowlessWindowsEglContext { + public: + class Configuration; + + /** + * @brief Constructor + * @param configuration Context configuration + * @param context Optional Magnum context instance constructed + * using @ref NoCreate to manage driver workarounds + * + * Once the context is created, make it current using @ref makeCurrent() + * and create @ref Platform::Context instance to be able to use Magnum. + * @see @ref isCreated() + */ + explicit WindowlessWindowsEglContext(const Configuration& configuration, Context* context = nullptr); + + /** + * @brief Construct without creating the context + * + * Move a instance with created context over to make it usable. + */ + explicit WindowlessWindowsEglContext(NoCreateT) {} + + /** @brief Copying is not allowed */ + WindowlessWindowsEglContext(const WindowlessWindowsEglContext&) = delete; + + /** @brief Move constructor */ + WindowlessWindowsEglContext(WindowlessWindowsEglContext&& other); + + /** @brief Copying is not allowed */ + WindowlessWindowsEglContext& operator=(const WindowlessWindowsEglContext&) = delete; + + /** @brief Move assignment */ + WindowlessWindowsEglContext& operator=(WindowlessWindowsEglContext&& other); + + /** + * @brief Destructor + * + * Destroys the context, if any. + */ + ~WindowlessWindowsEglContext(); + + /** @brief Whether the context is created */ + bool isCreated() const { return _context; } + + /** + * @brief Make the context current + * + * Prints error message and returns `false` on failure, otherwise + * returns `true`. + */ + bool makeCurrent(); + + private: + HWND _window{}; + EGLDisplay _display{}; + EGLSurface _surface{}; + EGLContext _context{}; +}; + +/** +@brief Configuration + +@see @ref WindowlessWindowsEglContext(), + @ref WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(), + @ref WindowlessWindowsEglApplication::createContext(), + @ref WindowlessWindowsEglApplication::tryCreateContext() +*/ +class WindowlessWindowsEglContext::Configuration { + public: + /** + * @brief Context flag + * + * @see @ref Flags, @ref setFlags(), @ref Context::Flag + */ + enum class Flag: int { + Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR /**< Create debug context */ + }; + + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + typedef Containers::EnumSet Flags; + #else + typedef Containers::EnumSet Flags; + #endif + + constexpr /*implicit*/ Configuration() {} + + /** @brief Context flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. See also @ref Context::flags(). + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } -Application for offscreen rendering using pure WINAPI and EGL. + private: + Flags _flags; +}; + +/** +@brief Windowless Windows/EGL application +Application for offscreen rendering using @ref WindowlessWindowsEglContext. This application library is available on OpenGL ES (also ANGLE) on Windows. It is built if `WITH_WINDOWLESSWINDOWSEGLAPPLICATION` is enabled in CMake. @@ -97,22 +218,30 @@ class WindowlessWindowsEglApplication { /** @brief Application arguments */ struct Arguments { /** @brief Constructor */ - /*implicit*/ constexpr Arguments(int& argc, char** argv, HWND window) noexcept: argc{argc}, argv{argv}, window{window} {} + /*implicit*/ constexpr Arguments(int& argc, char** argv) noexcept: argc{argc}, argv{argv} {} int& argc; /**< @brief Argument count */ char** argv; /**< @brief Argument values */ - #ifndef DOXYGEN_GENERATING_OUTPUT - HWND window; - #endif }; - class Configuration; - - #ifndef DOXYGEN_GENERATING_OUTPUT - static int create(LRESULT(CALLBACK windowProcedure)(HWND, UINT, WPARAM, LPARAM)); - #endif + /** + * @brief Configuration + * + * @see @ref WindowlessWindowsEglApplication(), @ref createContext(), + * @ref tryCreateContext() + */ + typedef WindowlessWindowsEglContext::Configuration Configuration; - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + /** + * @brief Default constructor + * @param arguments Application arguments + * @param configuration Configuration + * + * Creates application with default or user-specified configuration. + * See @ref Configuration for more information. The program exits if + * the context cannot be created, see @ref tryCreateContext() for an + * alternative. + */ #ifdef DOXYGEN_GENERATING_OUTPUT explicit WindowlessWindowsEglApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); #else @@ -121,8 +250,22 @@ class WindowlessWindowsEglApplication { explicit WindowlessWindowsEglApplication(const Arguments& arguments); #endif - /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ - explicit WindowlessWindowsEglApplication(const Arguments& arguments, std::nullptr_t); + /** + * @brief Constructor + * @param arguments Application arguments + * + * Unlike above, the context is not created and must be created later + * with @ref createContext() or @ref tryCreateContext(). + */ + explicit WindowlessWindowsEglApplication(const Arguments& arguments, NoCreateT); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief WindowlessWindowsEglApplication(const Arguments&, NoCreateT) + * @deprecated Use @ref WindowlessWindowsEglApplication(const Arguments&, NoCreateT) instead. + */ + CORRADE_DEPRECATED("use WindowlessWindowsEglApplication(const Arguments&, NoCreateT) instead") explicit WindowlessWindowsEglApplication(const Arguments& arguments, std::nullptr_t): WindowlessWindowsEglApplication{arguments, NoCreate} {} + #endif /** @brief Copying is not allowed */ WindowlessWindowsEglApplication(const WindowlessWindowsEglApplication&) = delete; @@ -150,7 +293,14 @@ class WindowlessWindowsEglApplication { thus this is faster than public pure virtual destructor */ ~WindowlessWindowsEglApplication(); - /** @copydoc Sdl2Application::createContext() */ + /** + * @brief Create context with given configuration + * + * Must be called if and only if the context wasn't created by the + * constructor itself. Error message is printed and the program exits + * if the context cannot be created, see @ref tryCreateContext() for an + * alternative. + */ #ifdef DOXYGEN_GENERATING_OUTPUT void createContext(const Configuration& configuration = Configuration()); #else @@ -159,65 +309,17 @@ class WindowlessWindowsEglApplication { void createContext(); #endif - /** @copydoc Sdl2Application::tryCreateContext() */ - bool tryCreateContext(const Configuration& configuration); - - private: - HWND _window; - EGLDisplay _display; - EGLConfig _config; - EGLSurface _surface; - EGLContext _glContext; - - std::unique_ptr _context; -}; - -/** -@brief Configuration - -@see @ref WindowlessWindowsEglApplication(), @ref createContext(), - @ref tryCreateContext() -*/ -class WindowlessWindowsEglApplication::Configuration { - public: - /** - * @brief Context flag - * - * @see @ref Flags, @ref setFlags(), @ref Context::Flag - */ - enum class Flag: int { - Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR /**< Create debug context */ - }; - - /** - * @brief Context flags - * - * @see @ref setFlags(), @ref Context::Flags - */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else - typedef Containers::EnumSet Flags; - #endif - - constexpr /*implicit*/ Configuration() {} - - /** @brief Context flags */ - Flags flags() const { return _flags; } - /** - * @brief Set context flags - * @return Reference to self (for method chaining) + * @brief Try to create context with given configuration * - * Default is no flag. See also @ref Context::flags(). + * Unlike @ref createContext() returns `false` if the context cannot be + * created, `true` otherwise. */ - Configuration& setFlags(Flags flags) { - _flags = flags; - return *this; - } + bool tryCreateContext(const Configuration& configuration); private: - Flags _flags; + WindowlessWindowsEglContext _glContext; + std::unique_ptr _context; }; /** @hideinitializer @@ -230,30 +332,16 @@ code, see @ref portability-applications for more information. When no other windowless application header is included this macro is also aliased to `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`. */ -#define MAGNUM_WINDOWLESSWINDOWSEGLAPPLICATION_MAIN(className) \ - int globalArgc; char** globalArgv; \ - LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); \ - LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { \ - switch(message) { \ - case WM_CREATE: \ - { \ - className app({globalArgc, globalArgv, hWnd}); \ - PostQuitMessage(app.exec()); \ - } \ - break; \ - default: return DefWindowProc(hWnd, message, wParam, lParam); \ - } \ - return 0; \ - } \ +#define MAGNUM_WINDOWLESSWINDOWSEGLAPPLICATION_MAIN(className) \ int main(int argc, char** argv) { \ - globalArgc = argc; \ - globalArgv = argv; \ - return Magnum::Platform::WindowlessWindowsEglApplication::create(windowProcedure); \ + className app({argc, argv}); \ + return app.exec(); \ } #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN typedef WindowlessWindowsEglApplication WindowlessApplication; +typedef WindowlessWindowsEglContext WindowlessGLContext; #define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSWINDOWSEGLAPPLICATION_MAIN(className) #else #undef MAGNUM_WINDOWLESSAPPLICATION_MAIN diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 68cf49f56..630a6c81e 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -66,7 +66,11 @@ #elif defined(CORRADE_TARGET_APPLE) #include "Magnum/Platform/WindowlessCglApplication.h" #elif defined(CORRADE_TARGET_UNIX) +#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_DESKTOP_GLES) +#include "Magnum/Platform/WindowlessEglApplication.h" +#else #include "Magnum/Platform/WindowlessGlxApplication.h" +#endif #elif defined(CORRADE_TARGET_WINDOWS) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_DESKTOP_GLES) #include "Magnum/Platform/WindowlessWglApplication.h" @@ -115,7 +119,7 @@ Using optional features: GL_ARB_invalidate_subdata ... Using driver workarounds: - amd-nv-no-forward-compatible-core-context + no-forward-compatible-core-context no-layout-qualifiers-on-old-glsl Context flags: Supported GLSL versions: @@ -141,7 +145,7 @@ class MagnumInfo: public Platform::WindowlessApplication { int exec() override { return 0; } }; -MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplication(arguments, nullptr) { +MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { Utility::Arguments args; args.addBooleanOption('s', "short").setHelp("short", "display just essential info and exit") .addBooleanOption("extension-strings").setHelp("extension-strings", "list all extension strings provided by the driver (implies --short)") @@ -246,6 +250,9 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat #ifdef MAGNUM_BUILD_STATIC Debug() << " MAGNUM_BUILD_STATIC"; #endif + #ifdef MAGNUM_BUILD_MULTITHREADED + Debug() << " MAGNUM_BUILD_MULTITHREADED"; + #endif #ifdef MAGNUM_TARGET_GLES Debug() << " MAGNUM_TARGET_GLES"; #endif @@ -605,6 +612,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _h(ARB::transform_feedback3) _l(TransformFeedback::maxBuffers()) + _l(TransformFeedback::maxVertexStreams()) } #endif diff --git a/src/Magnum/PrimitiveQuery.cpp b/src/Magnum/PrimitiveQuery.cpp new file mode 100644 index 000000000..e2c989939 --- /dev/null +++ b/src/Magnum/PrimitiveQuery.cpp @@ -0,0 +1,69 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "PrimitiveQuery.h" + +namespace Magnum { + +void PrimitiveQuery::begin() { + #ifndef MAGNUM_TARGET_GLES + _index = 0; + #endif + AbstractQuery::begin(); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +void PrimitiveQuery::begin(const Target target) { + #ifndef MAGNUM_TARGET_GLES + _index = 0; + #endif + AbstractQuery::begin(GLenum(target)); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void PrimitiveQuery::begin(const UnsignedInt index) { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_INTERNAL_ASSERT(_target); + #endif + + glBeginQueryIndexed(_target, _index = index, _id); +} +#endif + +void PrimitiveQuery::end() { + #ifdef MAGNUM_BUILD_DEPRECATED + CORRADE_INTERNAL_ASSERT(_target); + #endif + + #ifndef MAGNUM_TARGET_GLES + if(!_index) glEndQuery(_target); + else glEndQueryIndexed(_target, _index); + #else + AbstractQuery::end(); + #endif +} + +} diff --git a/src/Magnum/PrimitiveQuery.h b/src/Magnum/PrimitiveQuery.h index 0e84eba61..344dfdae4 100644 --- a/src/Magnum/PrimitiveQuery.h +++ b/src/Magnum/PrimitiveQuery.h @@ -63,25 +63,61 @@ UnsignedInt primitiveCount = q.result(); @requires_gl30 Extension @extension{EXT,transform_feedback} @requires_gles30 Only sample queries are available in OpenGL ES 2.0. @requires_webgl20 Queries are not available in WebGL 1.0. -@todo glBeginQueryIndexed -@todo @extension{ARB,transform_feedback_overflow_query} */ -class PrimitiveQuery: public AbstractQuery { +class MAGNUM_EXPORT PrimitiveQuery: public AbstractQuery { public: /** @brief Query target */ enum class Target: GLenum { - #ifndef MAGNUM_TARGET_GLES + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) /** * Count of primitives generated from vertex shader or geometry - * shader. - * @requires_gl Only transform feedback query is available in - * OpenGL ES and WebGL. + * shader. When used with @ref begin(UnsignedInt), the index must + * be lower than @ref TransformFeedback::maxVertexStreams(). Use + * @ref result() or @ref result() to retrieve the + * result. + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/ + * @es_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. */ + #ifndef MAGNUM_TARGET_GLES PrimitivesGenerated = GL_PRIMITIVES_GENERATED, + #else + PrimitivesGenerated = GL_PRIMITIVES_GENERATED_EXT, #endif + #endif + + /** + * Count of primitives written to transform feedback buffer. When + * used with @ref begin(UnsignedInt), the index must be lower than + * @ref TransformFeedback::maxVertexStreams(). Use + * @ref result() or @ref result() to retrieve the + * result. + */ + TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, + + #ifndef MAGNUM_TARGET_GLES + /** + * Transform feedback overflow. When used with @ref begin(UnsignedInt), + * the index must be `0`. Use @ref result() to retrieve the + * result. + * @requires_extension Extension @extension{ARB,transform_feedback_overflow_query} + * @requires_gl Transform feedback overflow query is not available + * in OpenGL ES or WebGL. + */ + TransformFeedbackOverflow = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, - /** Count of primitives written to transform feedback buffer. */ - TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN + /** + * Transform feedback stream overflow. When used with + * @ref begin(UnsignedInt), the index must be lower than + * @ref TransformFeedback::maxVertexStreams(). Use @ref result() + * to retrieve the result. + * @requires_extension Extension @extension{ARB,transform_feedback_overflow_query} + * @requires_gl Transform feedback overflow query is not available + * in OpenGL ES or WebGL. + */ + TransformFeedbackStreamOverflow = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB + #endif }; /** @@ -129,18 +165,49 @@ class PrimitiveQuery: public AbstractQuery { */ explicit PrimitiveQuery(NoCreateT) noexcept: AbstractQuery{NoCreate, GLenum(Target::TransformFeedbackPrimitivesWritten)} {} + /** + * @brief Begin query + * + * Begins counting until @ref end() is called. Equivalent to calling + * @ref begin(UnsignedInt) with @p index set to `0`. + * @see @fn_gl{BeginQuery} + */ + void begin(); + #ifdef MAGNUM_BUILD_DEPRECATED /** - * @copybrief AbstractQuery::begin() + * @copybrief begin() * @deprecated Use @ref begin() instead. */ - CORRADE_DEPRECATED("use begin() instead") void begin(Target target) { - AbstractQuery::begin(GLenum(target)); - } + CORRADE_DEPRECATED("use begin() instead") void begin(Target target); + #endif - using AbstractQuery::begin; + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Begin indexed query + * + * Begins counting until @ref end() is called. + * @see @fn_gl{BeginQueryIndexed} + * @requires_gl40 Extension @extension{ARB,transform_feedback3} + * @requires_gl Indexed queries are not available in OpenGL ES or WebGL. + */ + void begin(UnsignedInt index); #endif + /** + * @brief End query + * + * Ends the non-indexed or indexed query started with @ref begin() or + * @ref begin(UnsignedInt). The result can be then retrieved by calling + * @ref result(). + * @see @fn_gl{EndQuery}, @fn_gl2{EndQueryIndexed,BeginQueryIndexed} + * @requires_gl40 Extension @extension{ARB,transform_feedback3} for + * indexed queries + * @requires_gl Indexed queries are not available in OpenGL ES or + * WebGL. + */ + void end(); + /* Overloads to remove WTF-factor from method chaining order */ #if !defined(DOXYGEN_GENERATING_OUTPUT) && !defined(MAGNUM_TARGET_WEBGL) PrimitiveQuery& setLabel(const std::string& label) { @@ -155,6 +222,10 @@ class PrimitiveQuery: public AbstractQuery { private: explicit PrimitiveQuery(GLuint id, Target target, ObjectFlags flags) noexcept: AbstractQuery{id, GLenum(target), flags} {} + + #ifndef MAGNUM_TARGET_GLES + GLuint _index{}; + #endif }; } diff --git a/src/Magnum/Renderbuffer.cpp b/src/Magnum/Renderbuffer.cpp index 6a090d29e..a11b002b1 100644 --- a/src/Magnum/Renderbuffer.cpp +++ b/src/Magnum/Renderbuffer.cpp @@ -169,7 +169,7 @@ void Renderbuffer::storageMultisampleImplementationANGLE(const GLsizei samples, static_cast(samples); static_cast(internalFormat); static_cast(size); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -181,7 +181,7 @@ void Renderbuffer::storageMultisampleImplementationNV(const GLsizei samples, con static_cast(samples); static_cast(internalFormat); static_cast(size); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif diff --git a/src/Magnum/Renderer.cpp b/src/Magnum/Renderer.cpp index fba5e0ec1..5fcad0bba 100644 --- a/src/Magnum/Renderer.cpp +++ b/src/Magnum/Renderer.cpp @@ -94,7 +94,7 @@ void Renderer::setPolygonMode(const PolygonMode mode) { (GL_FRONT_AND_BACK, GLenum(mode)); #else static_cast(mode); - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -208,7 +208,8 @@ Renderer::GraphicsResetStatus Renderer::graphicsResetStatus() { void Renderer::initializeContextBasedFunctionality() { /* Set some "corporate identity" */ - setClearColor(Color3(0.125f)); + using namespace Magnum::Math::Literals; + setClearColor(0x1f1f1f_rgbf); } #ifndef MAGNUM_TARGET_GLES @@ -232,7 +233,7 @@ Renderer::GraphicsResetStatus Renderer::graphicsResetStatusImplementationRobustn #elif !defined(CORRADE_TARGET_NACL) return GraphicsResetStatus(glGetGraphicsResetStatusEXT()); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } #endif @@ -240,6 +241,7 @@ Renderer::GraphicsResetStatus Renderer::graphicsResetStatusImplementationRobustn #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const Renderer::Error value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Renderer::Error::value: return debug << "Renderer::Error::" #value; _c(NoError) _c(InvalidEnum) @@ -252,34 +254,39 @@ Debug& operator<<(Debug& debug, const Renderer::Error value) { _c(StackOverflow) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Renderer::Error::(invalid)"; + return debug << "Renderer::Error(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #ifndef MAGNUM_TARGET_WEBGL Debug& operator<<(Debug& debug, const Renderer::ResetNotificationStrategy value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Renderer::ResetNotificationStrategy::value: return debug << "Renderer::ResetNotificationStrategy::" #value; _c(NoResetNotification) _c(LoseContextOnReset) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Renderer::ResetNotificationStrategy::(invalid)"; + return debug << "Renderer::ResetNotificationStrategy(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const Renderer::GraphicsResetStatus value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Renderer::GraphicsResetStatus::value: return debug << "Renderer::GraphicsResetStatus::" #value; _c(NoError) _c(GuiltyContextReset) _c(InnocentContextReset) _c(UnknownContextReset) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Renderer::ResetNotificationStrategy::(invalid)"; + return debug << "Renderer::GraphicsResetStatus(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif #endif diff --git a/src/Magnum/Resource.cpp b/src/Magnum/Resource.cpp index 8106b18ed..678453048 100644 --- a/src/Magnum/Resource.cpp +++ b/src/Magnum/Resource.cpp @@ -30,6 +30,7 @@ namespace Magnum { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const ResourceState value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case ResourceState::value: return debug << "ResourceState::" #value; _c(NotLoaded) _c(NotLoadedFallback) @@ -40,9 +41,10 @@ Debug& operator<<(Debug& debug, const ResourceState value) { _c(Mutable) _c(Final) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "ResourceState::(invalid)"; + return debug << "ResourceState(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/ResourceManager.hpp b/src/Magnum/ResourceManager.hpp index d0fc54225..02a10e73b 100644 --- a/src/Magnum/ResourceManager.hpp +++ b/src/Magnum/ResourceManager.hpp @@ -1,3 +1,5 @@ +#ifndef Magnum_ResourceManager_hpp +#define Magnum_ResourceManager_hpp /* This file is part of Magnum. @@ -48,3 +50,5 @@ ResourceManager*& ResourceManagerLocalInstanceImplementation } }} + +#endif diff --git a/src/Magnum/SampleQuery.h b/src/Magnum/SampleQuery.h index 00432c687..608ee4da5 100644 --- a/src/Magnum/SampleQuery.h +++ b/src/Magnum/SampleQuery.h @@ -86,7 +86,9 @@ class SampleQuery: public AbstractQuery { enum class Target: GLenum { #ifndef MAGNUM_TARGET_GLES /** - * Count of samples passed from fragment shader + * Count of samples passed from fragment shader. Use + * @ref result() or @ref result() to retrieve the + * result. * @requires_gl Only boolean query is available in OpenGL ES and * WebGL. */ @@ -94,7 +96,8 @@ class SampleQuery: public AbstractQuery { #endif /** - * Whether any samples passed from fragment shader + * Whether any samples passed from fragment shader. Use + * @ref result() to retrieve the result. * @requires_gl33 Extension @extension{ARB,occlusion_query2} */ #ifndef MAGNUM_TARGET_GLES2 @@ -104,10 +107,10 @@ class SampleQuery: public AbstractQuery { #endif /** - * Whether any samples passed from fragment shader (conservative) - * - * An implementation may choose a less precise version of the - * test at the expense of some false positives. + * Whether any samples passed from fragment shader (conservative). + * An implementation may choose a less precise version of the test + * at the expense of some false positives. Use @ref result() + * to retrieve the result. * @requires_gl43 Extension @extension{ARB,ES3_compatibility} */ #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/Sampler.cpp b/src/Magnum/Sampler.cpp index e2a8fee14..f4cb95804 100644 --- a/src/Magnum/Sampler.cpp +++ b/src/Magnum/Sampler.cpp @@ -63,29 +63,34 @@ Float Sampler::maxMaxAnisotropy() { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const Sampler::Filter value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Sampler::Filter::value: return debug << "Sampler::Filter::" #value; _c(Nearest) _c(Linear) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Sampler::Filter::(invalid)"; + return debug << "Sampler::Filter(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const Sampler::Mipmap value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Sampler::Mipmap::value: return debug << "Sampler::Mipmap::" #value; _c(Base) _c(Nearest) _c(Linear) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Sampler::Mipmap::(invalid)"; + return debug << "Sampler::Mipmap(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const Sampler::Wrapping value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Sampler::Wrapping::value: return debug << "Sampler::Wrapping::" #value; _c(Repeat) _c(MirroredRepeat) @@ -97,25 +102,29 @@ Debug& operator<<(Debug& debug, const Sampler::Wrapping value) { _c(MirrorClampToEdge) #endif #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Sampler::Wrapping::(invalid)"; + return debug << "Sampler::Wrapping(" << Debug::nospace << reinterpret_cast(GLint(value)) << Debug::nospace << ")"; } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) Debug& operator<<(Debug& debug, const Sampler::CompareMode value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Sampler::CompareMode::value: return debug << "Sampler::CompareMode::" #value; _c(None) _c(CompareRefToTexture) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Sampler::CompareFunction::(invalid)"; + return debug << "Sampler::CompareMode(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const Sampler::CompareFunction value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Sampler::CompareFunction::value: return debug << "Sampler::CompareFunction::" #value; _c(Never) _c(Always) @@ -126,22 +135,25 @@ Debug& operator<<(Debug& debug, const Sampler::CompareFunction value) { _c(GreaterOrEqual) _c(Greater) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Sampler::CompareFunction::(invalid)"; + return debug << "Sampler::CompareFunction(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif #ifndef MAGNUM_TARGET_GLES Debug& operator<<(Debug& debug, const Sampler::DepthStencilMode value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Sampler::DepthStencilMode::value: return debug << "Sampler::DepthStencilMode::" #value; _c(DepthComponent) _c(StencilIndex) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Sampler::DepthStencilMode::(invalid)"; + return debug << "Sampler::DepthStencilMode(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif #endif diff --git a/src/Magnum/SceneGraph/AbstractObject.h b/src/Magnum/SceneGraph/AbstractObject.h index 4f0c60adf..bb752f4e3 100644 --- a/src/Magnum/SceneGraph/AbstractObject.h +++ b/src/Magnum/SceneGraph/AbstractObject.h @@ -170,6 +170,12 @@ template class AbstractObject /** @overload */ const AbstractObject* scene() const { return doScene(); } + /** @brief Parent object or `nullptr`, if this is root object */ + AbstractObject* parent() { return doParent(); } + + /** @overload */ + const AbstractObject* parent() const { return doParent(); } + /** @{ @name Object transformation */ /** @@ -269,6 +275,9 @@ template class AbstractObject virtual AbstractObject* doScene() = 0; virtual const AbstractObject* doScene() const = 0; + virtual AbstractObject* doParent() = 0; + virtual const AbstractObject* doParent() const = 0; + virtual MatrixType doTransformationMatrix() const = 0; virtual MatrixType doAbsoluteTransformationMatrix() const = 0; virtual std::vector doTransformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix) const = 0; diff --git a/src/Magnum/SceneGraph/AbstractTranslation.h b/src/Magnum/SceneGraph/AbstractTranslation.h index 834a3dfb4..bacbadf3e 100644 --- a/src/Magnum/SceneGraph/AbstractTranslation.h +++ b/src/Magnum/SceneGraph/AbstractTranslation.h @@ -82,6 +82,10 @@ class AbstractTranslation: public AbstractTransformation { } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief translate() * @deprecated Use @ref translate() or @ref translateLocal() instead. @@ -89,6 +93,9 @@ class AbstractTranslation: public AbstractTransformation { CORRADE_DEPRECATED("use translate() or translateLocal() instead") AbstractTranslation& translate(const VectorTypeFor& vector, TransformationType type) { return type == TransformationType::Global ? translate(vector) : translateLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /* Overloads to remove WTF-factor from method chaining order */ diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h b/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h index f5a7bf747..266af3911 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotation2D.h @@ -70,6 +70,10 @@ template class AbstractBasicTranslationRotation2D: public AbstractBasic } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -77,6 +81,9 @@ template class AbstractBasicTranslationRotation2D: public AbstractBasic CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") AbstractBasicTranslationRotation2D& rotate(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotate(angle) : rotateLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /* Overloads to remove WTF-factor from method chaining order */ @@ -94,6 +101,10 @@ template class AbstractBasicTranslationRotation2D: public AbstractBasic return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use translate() or translateLocal() instead") AbstractBasicTranslationRotation2D& translate(const Math::Vector2& vector, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -101,6 +112,9 @@ template class AbstractBasicTranslationRotation2D: public AbstractBasic AbstractBasicTranslation2D::translate(vector, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif #endif diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h b/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h index 72a3bdef3..be8624a94 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotation3D.h @@ -74,6 +74,10 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -81,6 +85,9 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") AbstractBasicTranslationRotation3D& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) { return type == TransformationType::Global ? rotate(angle, normalizedAxis) : rotateLocal(angle, normalizedAxis); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -112,6 +119,10 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateX() * @deprecated Use @ref rotateX() or @ref rotateXLocal() instead. @@ -119,6 +130,9 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic CORRADE_DEPRECATED("use rotateX() or rotateXLocal() instead") AbstractBasicTranslationRotation3D& rotateX(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateX(angle) : rotateXLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -150,6 +164,10 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateY() * @deprecated Use @ref rotateY() or @ref rotateYLocal() instead. @@ -157,6 +175,9 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic CORRADE_DEPRECATED("use rotateY() or rotateYLocal() instead") AbstractBasicTranslationRotation3D& rotateY(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateY(angle) : rotateYLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -188,6 +209,10 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateZ() * @deprecated Use @ref rotateZ() or @ref rotateZLocal() instead. @@ -195,6 +220,9 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic CORRADE_DEPRECATED("use rotateZ() or rotateZLocal() instead") AbstractBasicTranslationRotation3D& rotateZ(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateZ(angle) : rotateZLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /* Overloads to remove WTF-factor from method chaining order */ @@ -212,6 +240,10 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use translate() or translateLocal() instead") AbstractBasicTranslationRotation3D& translate(const Math::Vector3& vector, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -219,6 +251,9 @@ template class AbstractBasicTranslationRotation3D: public AbstractBasic AbstractBasicTranslation3D::translate(vector, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif #endif diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h index e7a04425e..e7f21034f 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h @@ -70,6 +70,10 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief scale() * @deprecated Use @ref scale() or @ref scaleLocal() instead. @@ -77,6 +81,9 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra CORRADE_DEPRECATED("use scale() or scaleLocal() instead") AbstractBasicTranslationRotationScaling2D& scale(const Math::Vector2& vector, TransformationType type) { return type == TransformationType::Global ? scale(vector) : scaleLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /* Overloads to remove WTF-factor from method chaining order */ @@ -94,6 +101,10 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use translate() or translateLocal() instead") AbstractBasicTranslationRotationScaling2D& translate(const Math::Vector2& vector, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -101,6 +112,9 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra AbstractBasicTranslationRotation2D::translate(vector, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif AbstractBasicTranslationRotationScaling2D& rotate(Math::Rad angle) { AbstractBasicTranslationRotation2D::rotate(angle); @@ -111,6 +125,10 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") AbstractBasicTranslationRotationScaling2D& rotate(Math::Rad angle, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -118,6 +136,9 @@ template class AbstractBasicTranslationRotationScaling2D: public Abstra AbstractBasicTranslationRotation2D::rotate(angle, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif #endif diff --git a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h index f8078b880..2361c8316 100644 --- a/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h +++ b/src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h @@ -70,6 +70,10 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief scale() * @deprecated Use @ref scale() or @ref scaleLocal() instead. @@ -80,6 +84,9 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra #endif return type == TransformationType::Global ? scale(vector) : scaleLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /* Overloads to remove WTF-factor from method chaining order */ @@ -97,6 +104,10 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use translate() or translateLocal() instead") AbstractBasicTranslationRotationScaling3D& translate(const Math::Vector3& vector, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -104,6 +115,9 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra AbstractBasicTranslationRotation3D::translate(vector, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif AbstractBasicTranslationRotationScaling3D& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis) { AbstractBasicTranslationRotation3D::rotate(angle, normalizedAxis); @@ -114,6 +128,10 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") AbstractBasicTranslationRotationScaling3D& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -121,6 +139,9 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra AbstractBasicTranslationRotation3D::rotate(angle, normalizedAxis, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif AbstractBasicTranslationRotationScaling3D& rotateX(Math::Rad angle) { AbstractBasicTranslationRotation3D::rotateX(angle); @@ -131,6 +152,10 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotateX() or rotateXLocal() instead") AbstractBasicTranslationRotationScaling3D& rotateX(Math::Rad angle, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -138,6 +163,9 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra AbstractBasicTranslationRotation3D::rotateX(angle, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif AbstractBasicTranslationRotationScaling3D& rotateY(Math::Rad angle) { AbstractBasicTranslationRotation3D::rotateY(angle); @@ -148,6 +176,10 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotateY() or rotateYLocal() instead") AbstractBasicTranslationRotationScaling3D& rotateY(Math::Rad angle, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -155,6 +187,9 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra AbstractBasicTranslationRotation3D::rotateY(angle, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif AbstractBasicTranslationRotationScaling3D& rotateZ(Math::Rad angle) { AbstractBasicTranslationRotation3D::rotateZ(angle); @@ -165,6 +200,10 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra return *this; } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotateZ() or rotateZLocal() instead") AbstractBasicTranslationRotationScaling3D& rotateZ(Math::Rad angle, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) @@ -172,6 +211,9 @@ template class AbstractBasicTranslationRotationScaling3D: public Abstra AbstractBasicTranslationRotation3D::rotateZ(angle, type); return *this; } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif #endif diff --git a/src/Magnum/SceneGraph/Animable.cpp b/src/Magnum/SceneGraph/Animable.cpp index 4ea4ce845..6bbcb843a 100644 --- a/src/Magnum/SceneGraph/Animable.cpp +++ b/src/Magnum/SceneGraph/Animable.cpp @@ -31,14 +31,16 @@ namespace Magnum { namespace SceneGraph { Debug& operator<<(Debug& debug, AnimationState value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case AnimationState::value: return debug << "SceneGraph::AnimationState::" #value; _c(Stopped) _c(Paused) _c(Running) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "SceneGraph::AnimationState::(invalid)"; + return debug << "SceneGraph::AnimationState(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } }} diff --git a/src/Magnum/SceneGraph/Camera.hpp b/src/Magnum/SceneGraph/Camera.hpp index a176ada83..5bb197d4c 100644 --- a/src/Magnum/SceneGraph/Camera.hpp +++ b/src/Magnum/SceneGraph/Camera.hpp @@ -49,8 +49,8 @@ template MatrixTypeFor aspectRat Clip on smaller side = scale smaller side up */ return MatrixTypeFor::scaling(Math::Vector::pad( (relativeAspectRatio.x() > relativeAspectRatio.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ? - Vector2(relativeAspectRatio.y()/relativeAspectRatio.x(), T(1)) : - Vector2(T(1), relativeAspectRatio.x()/relativeAspectRatio.y()), T(1))); + Math::Vector2(relativeAspectRatio.y()/relativeAspectRatio.x(), T(1)) : + Math::Vector2(T(1), relativeAspectRatio.x()/relativeAspectRatio.y()), T(1))); } } diff --git a/src/Magnum/SceneGraph/DualComplexTransformation.h b/src/Magnum/SceneGraph/DualComplexTransformation.h index 1df8a21d1..9c15382e1 100644 --- a/src/Magnum/SceneGraph/DualComplexTransformation.h +++ b/src/Magnum/SceneGraph/DualComplexTransformation.h @@ -110,6 +110,10 @@ template class BasicDualComplexTransformation: public AbstractBasicTran } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief transform() * @deprecated Use @ref transform() or @ref transformLocal() instead. @@ -117,6 +121,9 @@ template class BasicDualComplexTransformation: public AbstractBasicTran CORRADE_DEPRECATED("use transform() or transformLocal() instead") Object>& transform(const Math::DualComplex& transformation, TransformationType type) { return type == TransformationType::Global ? transform(transformation) : transformLocal(transformation); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -143,6 +150,10 @@ template class BasicDualComplexTransformation: public AbstractBasicTran } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief translate() * @deprecated Use @ref translate() or @ref translateLocal() instead. @@ -150,6 +161,9 @@ template class BasicDualComplexTransformation: public AbstractBasicTran CORRADE_DEPRECATED("use translate() or translateLocal() instead") Object>& translate(const Math::Vector2& vector, TransformationType type) { return type == TransformationType::Global ? translate(vector) : translateLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -175,6 +189,10 @@ template class BasicDualComplexTransformation: public AbstractBasicTran } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -182,6 +200,9 @@ template class BasicDualComplexTransformation: public AbstractBasicTran CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") Object>& rotate(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotate(angle) : rotateLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif protected: diff --git a/src/Magnum/SceneGraph/DualQuaternionTransformation.h b/src/Magnum/SceneGraph/DualQuaternionTransformation.h index 364a87569..dc957df2c 100644 --- a/src/Magnum/SceneGraph/DualQuaternionTransformation.h +++ b/src/Magnum/SceneGraph/DualQuaternionTransformation.h @@ -110,6 +110,10 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief transform() * @deprecated Use @ref transform() or @ref transformLocal() instead. @@ -117,6 +121,9 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT CORRADE_DEPRECATED("use transform() or transformLocal() instead") Object>& transform(const Math::DualQuaternion& transformation, TransformationType type) { return type == TransformationType::Global ? transform(transformation) : transformLocal(transformation); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -142,6 +149,10 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief translate() * @deprecated Use @ref translate() or @ref translateLocal() instead. @@ -149,6 +160,9 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT CORRADE_DEPRECATED("use translate() or translateLocal() instead") Object>& translate(const Math::Vector3& vector, TransformationType type) { return type == TransformationType::Global ? translate(vector) : translateLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -177,6 +191,10 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -184,6 +202,9 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT CORRADE_DEPRECATED("usr rotate() or rotateLocal() instead") Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) { return type == TransformationType::Global ? rotate(angle, normalizedAxis) : rotateLocal(angle, normalizedAxis); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /* Overloads to remove WTF-factor from method chaining order */ @@ -195,12 +216,19 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT return rotateLocal(angle, Math::Vector3::xAxis()); } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotateX() or rotateXLocal() instead") Object>& rotateX(Math::Rad angle, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) #endif return rotate(angle, Math::Vector3::xAxis(), type); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif Object>& rotateY(Math::Rad angle) { return rotate(angle, Math::Vector3::yAxis()); @@ -209,12 +237,19 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT return rotateLocal(angle, Math::Vector3::yAxis()); } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotateY() or rotateYLocal() instead") Object>& rotateY(Math::Rad angle, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) #endif return rotate(angle, Math::Vector3::yAxis(), type); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif Object>& rotateZ(Math::Rad angle) { return rotate(angle, Math::Vector3::zAxis()); @@ -223,12 +258,19 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT return rotateLocal(angle, Math::Vector3::zAxis()); } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif CORRADE_DEPRECATED("use rotateZ() or rotateZLocal() instead") Object>& rotateZ(Math::Rad angle, TransformationType type) { #ifdef _MSC_VER #pragma warning(suppress: 4996) #endif return rotate(angle, Math::Vector3::zAxis(), type); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif #endif diff --git a/src/Magnum/SceneGraph/MatrixTransformation2D.h b/src/Magnum/SceneGraph/MatrixTransformation2D.h index 680c35f6a..840232f1b 100644 --- a/src/Magnum/SceneGraph/MatrixTransformation2D.h +++ b/src/Magnum/SceneGraph/MatrixTransformation2D.h @@ -87,6 +87,10 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief transform() * @deprecated Use @ref transform() or @ref transformLocal() instead. @@ -94,6 +98,9 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla CORRADE_DEPRECATED("use transform() or transformLocal() instead") Object>& transform(const Math::Matrix3& transformation, TransformationType type) { return type == TransformationType::Global ? transform(transformation) : transformLocal(transformation); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */ @@ -125,6 +132,10 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief translate() * @deprecated Use @ref translate() or @ref translateLocal() instead. @@ -132,6 +143,9 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla CORRADE_DEPRECATED("use translate() or translateLocal() instead") Object>& translate(const Math::Vector2& vector, TransformationType type) { return type == TransformationType::Global ? translate(vector) : translateLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -158,6 +172,10 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -165,6 +183,9 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") Object>& rotate(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotate(angle) : rotateLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -191,6 +212,10 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief scale() * @deprecated Use @ref scale() or @ref scaleLocal() instead. @@ -198,6 +223,9 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla CORRADE_DEPRECATED("use scale() or scaleLocal() instead") Object>& scale(const Math::Vector2& vector, TransformationType type) { return type == TransformationType::Global ? scale(vector) : scaleLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -226,6 +254,10 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief reflect() * @deprecated Use @ref reflect() or @ref reflectLocal() instead. @@ -233,6 +265,9 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla CORRADE_DEPRECATED("use reflect() or reflectLocal() instead") Object>& reflect(const Math::Vector2& normal, TransformationType type) { return type == TransformationType::Global ? reflect(normal) : reflectLocal(normal); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif protected: diff --git a/src/Magnum/SceneGraph/MatrixTransformation3D.h b/src/Magnum/SceneGraph/MatrixTransformation3D.h index 6dca54140..329214ce6 100644 --- a/src/Magnum/SceneGraph/MatrixTransformation3D.h +++ b/src/Magnum/SceneGraph/MatrixTransformation3D.h @@ -92,6 +92,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief transform() * @deprecated Use @ref transform() or @ref transformLocal() instead. @@ -99,6 +103,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use transform() or transformLocal() instead") Object>& transform(const Math::Matrix4& transformation, TransformationType type) { return type == TransformationType::Global ? transform(transformation) : transformLocal(transformation); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -125,6 +132,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief translate() * @deprecated Use @ref translate() or @ref translateLocal() instead. @@ -132,6 +143,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use translate() or translateLocal() instead") Object>& translate(const Math::Vector3& vector, TransformationType type) { return type == TransformationType::Global ? translate(vector) : translateLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -161,6 +175,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -168,6 +186,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) { return type == TransformationType::Global ? rotate(angle, normalizedAxis) : rotateLocal(angle, normalizedAxis); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -194,6 +215,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateX() * @deprecated Use @ref rotateX() or @ref rotateXLocal() instead. @@ -201,6 +226,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use rotateX() or rotateXLocal() instead") Object>& rotateX(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateX(angle) : rotateXLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -227,6 +255,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateY() * @deprecated Use @ref rotateY() or @ref rotateYLocal() instead. @@ -234,6 +266,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use rotateY() or rotateYLocal() instead") Object>& rotateY(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateY(angle) : rotateYLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -260,6 +295,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateZ() * @deprecated Use @ref rotateZ() or @ref rotateZLocal() instead. @@ -267,6 +306,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use rotateZ() or rotateZLocal() instead") Object>& rotateZ(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateZ(angle) : rotateZLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -293,6 +335,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief scale() * @deprecated Use @ref scale() or @ref scaleLocal() instead. @@ -300,6 +346,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use scale() or scaleLocal() instead") Object>& scale(const Math::Vector3& vector, TransformationType type) { return type == TransformationType::Global ? scale(vector) : scaleLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -327,6 +376,10 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief reflect() * @deprecated Use @ref reflect() or @ref reflectLocal() instead. @@ -334,6 +387,9 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla CORRADE_DEPRECATED("use reflect() or reflectLocal() instead") Object>& reflect(const Math::Vector3& normal, TransformationType type) { return type == TransformationType::Global ? reflect(normal) : reflectLocal(normal); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif protected: diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index dbc4497ee..79fc084e2 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -363,6 +363,9 @@ template class Object: public AbstractObject* doScene() override final; const Object* doScene() const override final; + Object* doParent() override final; + const Object* doParent() const override final; + MatrixType MAGNUM_SCENEGRAPH_LOCAL doTransformationMatrix() const override final { return transformationMatrix(); } diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index e3ceaeaa4..8a2b0e5f9 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -69,6 +69,14 @@ template const Object* Object Object* Object::doParent() { + return parent(); +} + +template const Object* Object::doParent() const { + return parent(); +} + template Object& Object::setParent(Object* parent) { /* Skip if parent is already parent or this is scene (which cannot have parent) */ /** @todo Assert for setting parent to scene */ diff --git a/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h b/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h index 81a55b41a..e5f313432 100644 --- a/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h +++ b/src/Magnum/SceneGraph/RigidMatrixTransformation2D.h @@ -115,6 +115,10 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief transform() * @deprecated Use @ref transform() or @ref transformLocal() instead. @@ -122,6 +126,9 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr CORRADE_DEPRECATED("use transform() or transformLocal() instead") Object>& transform(const Math::Matrix3& transformation, TransformationType type) { return type == TransformationType::Global ? transform(transformation) : transformLocal(transformation); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -148,6 +155,10 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief translate() * @deprecated Use @ref translate() or @ref translateLocal() instead. @@ -155,6 +166,9 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr CORRADE_DEPRECATED("use translate() or translateLocal() instead") Object>& translate(const Math::Vector2& vector, TransformationType type) { return type == TransformationType::Global ? translate(vector) : translateLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -182,6 +196,10 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -189,6 +207,9 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") Object>& rotate(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotate(angle) : rotateLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -216,6 +237,10 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief reflect() * @deprecated Use @ref reflect() or @ref reflectLocal() instead. @@ -223,6 +248,9 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr CORRADE_DEPRECATED("use reflect() or reflectInternal() instead") Object>& reflect(const Math::Vector2& normal, TransformationType type) { return type == TransformationType::Global ? reflect(normal) : reflectLocal(normal); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif protected: diff --git a/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h b/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h index 4d73c01e1..63c1713fe 100644 --- a/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h +++ b/src/Magnum/SceneGraph/RigidMatrixTransformation3D.h @@ -114,6 +114,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief transform() * @deprecated Use @ref transform() or @ref transformLocal() instead. @@ -121,6 +125,9 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_DEPRECATED("use transform() or transformLocal() instead") Object>& transform(const Math::Matrix4& transformation, TransformationType type) { return type == TransformationType::Global ? transform(transformation) : transformLocal(transformation); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -147,6 +154,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief translate() * @deprecated Use @ref translate() or @ref translateLocal() instead. @@ -154,6 +165,9 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_DEPRECATED("use translate() or translateLocal() instead") Object>& translate(const Math::Vector3& vector, TransformationType type) { return type == TransformationType::Global ? translate(vector) : translateLocal(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -184,6 +198,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotate() * @deprecated Use @ref rotate() or @ref rotateLocal() instead. @@ -191,6 +209,9 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_DEPRECATED("use rotate() or rotateLocal() instead") Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) { return type == TransformationType::Global ? rotate(angle, normalizedAxis) : rotateLocal(angle, normalizedAxis); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -217,6 +238,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateX() * @deprecated Use @ref rotateX() or @ref rotateXLocal() instead. @@ -224,6 +249,9 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_DEPRECATED("use rotateX() or rotateXLocal() instead") Object>& rotateX(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateX(angle) : rotateXLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -250,6 +278,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateY() * @deprecated Use @ref rotateY() or @ref rotateYLocal() instead. @@ -257,6 +289,9 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_DEPRECATED("use rotateY() or rotateYLocal() instead") Object>& rotateY(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateY(angle) : rotateYLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -283,6 +318,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief rotateZ() * @deprecated Use @ref rotateZ() or @ref rotateZLocal() instead. @@ -290,6 +329,9 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_DEPRECATED("use rotateZ() or rotateZLocal() instead") Object>& rotateZ(Math::Rad angle, TransformationType type) { return type == TransformationType::Global ? rotateZ(angle) : rotateZLocal(angle); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -317,6 +359,10 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } #ifdef MAGNUM_BUILD_DEPRECATED + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif /** * @copybrief reflect() * @deprecated Use @ref reflect() or @ref reflectLocal() instead. @@ -324,6 +370,9 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_DEPRECATED("use reflect() or reflectLocal() instead") Object>& reflect(const Math::Vector3& normal, TransformationType type) { return type == TransformationType::Global ? reflect(normal) : reflectLocal(normal); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif protected: diff --git a/src/Magnum/SceneGraph/Test/AnimableTest.cpp b/src/Magnum/SceneGraph/Test/AnimableTest.cpp index 844cc2090..28911e177 100644 --- a/src/Magnum/SceneGraph/Test/AnimableTest.cpp +++ b/src/Magnum/SceneGraph/Test/AnimableTest.cpp @@ -353,8 +353,8 @@ void AnimableTest::pause() { void AnimableTest::debug() { std::ostringstream o; - Debug(&o) << AnimationState::Running; - CORRADE_COMPARE(o.str(), "SceneGraph::AnimationState::Running\n"); + Debug(&o) << AnimationState::Running << AnimationState(0xbe); + CORRADE_COMPARE(o.str(), "SceneGraph::AnimationState::Running SceneGraph::AnimationState(0xbe)\n"); } }}} diff --git a/src/Magnum/SceneGraph/TranslationTransformation.h b/src/Magnum/SceneGraph/TranslationTransformation.h index c0b140391..85412211e 100644 --- a/src/Magnum/SceneGraph/TranslationTransformation.h +++ b/src/Magnum/SceneGraph/TranslationTransformation.h @@ -95,6 +95,10 @@ class TranslationTransformation: public AbstractTranslation>& transform(const VectorTypeFor& transformation, TransformationType) { return transform(transformation); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif /** @@ -119,6 +126,10 @@ class TranslationTransformation: public AbstractTranslation>& translate(const VectorTypeFor& vector, TransformationType) { return translate(vector); } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif #endif protected: diff --git a/src/Magnum/Shader.cpp b/src/Magnum/Shader.cpp index eba5bb1ad..6d596a6fe 100644 --- a/src/Magnum/Shader.cpp +++ b/src/Magnum/Shader.cpp @@ -69,7 +69,7 @@ std::string shaderName(const Shader::Type type) { case Shader::Type::Fragment: return "fragment"; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } UnsignedInt typeToIndex(const Shader::Type type) { @@ -84,7 +84,7 @@ UnsignedInt typeToIndex(const Shader::Type type) { #endif } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } #ifndef MAGNUM_TARGET_GLES @@ -784,15 +784,26 @@ Shader& Shader::addSource(std::string source) { converter << (_sources.size()+1)/2; #endif - /* Fix line numbers, so line 41 of third added file is marked as 3(41). - Source 0 is the #version string added in constructor. */ - _sources.push_back("#line 1 " + + /* Fix line numbers, so line 41 of third added file is marked as 3(41) + in case shader version was not Version::None, because then source 0 + is the #version directive added in constructor. + + If version was Version::None, line 41 of third added file is marked + as 2(41). We apparently can't add even the #line directive before + the potential `#version` directive -- in that case the first source + file is not marked with any file number, thus having number 0. In + order to avoid complex logic in compile() where we assert for at + least some user-provided source, an empty string is added here + instead. */ + if(!_sources.empty()) _sources.push_back("#line 1 " + #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) std::to_string((_sources.size()+1)/2) + #else converter.str() + #endif '\n'); + else _sources.emplace_back(); + _sources.push_back(std::move(source)); } @@ -892,6 +903,7 @@ bool Shader::compile(std::initializer_list> shade #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const Shader::Type value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case Shader::Type::value: return debug << "Shader::Type::" #value; _c(Vertex) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -902,9 +914,10 @@ Debug& operator<<(Debug& debug, const Shader::Type value) { #endif _c(Fragment) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Shader::Type::(invalid)"; + return debug << "Shader::Type(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/Shader.h b/src/Magnum/Shader.h index 67347eaa7..c3678dff2 100644 --- a/src/Magnum/Shader.h +++ b/src/Magnum/Shader.h @@ -595,7 +595,9 @@ class MAGNUM_EXPORT Shader: public AbstractObject { * * Adds given source to source list, preceeded with @c \#line directive * marking first line of the source as `n(1)` where n is number of - * added source. If passed string is empty, the function does nothing. + * added source. The source number `0` is @c \#version directive added + * in constructor, if any. If passed string is empty, the function does + * nothing. * @see @ref addFile() */ Shader& addSource(std::string source); diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index bf0c5d2b9..5431be52c 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -119,7 +119,7 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri if(flags & Flag::DiffuseTexture) setDiffuseColor(Color4{1.0f}); setSpecularColor(Color4{1.0f}); - setLightColor(Color4{.0f}); + setLightColor(Color4{1.0f}); setShininess(80.0f); #endif } diff --git a/src/Magnum/Shapes/Test/ShapeImplementationTest.cpp b/src/Magnum/Shapes/Test/ShapeImplementationTest.cpp index 6f7d9f16c..f2efaf7cd 100644 --- a/src/Magnum/Shapes/Test/ShapeImplementationTest.cpp +++ b/src/Magnum/Shapes/Test/ShapeImplementationTest.cpp @@ -42,12 +42,12 @@ ShapeImplementationTest::ShapeImplementationTest() { void ShapeImplementationTest::debug() { std::ostringstream o; - Debug(&o) << Implementation::ShapeDimensionTraits<2>::Type::Composition; - CORRADE_COMPARE(o.str(), "Shapes::Shape2D::Type::Composition\n"); + Debug(&o) << Implementation::ShapeDimensionTraits<2>::Type::Composition << Implementation::ShapeDimensionTraits<2>::Type(0xbe); + CORRADE_COMPARE(o.str(), "Shapes::Shape2D::Type::Composition Shapes::Shape2D::Type(0xbe)\n"); o.str({}); - Debug(&o) << Implementation::ShapeDimensionTraits<3>::Type::Plane; - CORRADE_COMPARE(o.str(), "Shapes::Shape3D::Type::Plane\n"); + Debug(&o) << Implementation::ShapeDimensionTraits<3>::Type::Plane << Implementation::ShapeDimensionTraits<3>::Type(0xbe); + CORRADE_COMPARE(o.str(), "Shapes::Shape3D::Type::Plane Shapes::Shape3D::Type(0xbe)\n"); } }}} diff --git a/src/Magnum/Shapes/shapeImplementation.cpp b/src/Magnum/Shapes/shapeImplementation.cpp index b2fc534df..704efcf1c 100644 --- a/src/Magnum/Shapes/shapeImplementation.cpp +++ b/src/Magnum/Shapes/shapeImplementation.cpp @@ -31,6 +31,7 @@ namespace Magnum { namespace Shapes { namespace Implementation { Debug& operator<<(Debug& debug, ShapeDimensionTraits<2>::Type value) { switch(value) { + /* LCOV_EXCL_START */ #define _val(value) case ShapeDimensionTraits<2>::Type::value: return debug << "Shapes::Shape2D::Type::" #value; _val(Point) _val(Line) @@ -43,13 +44,15 @@ Debug& operator<<(Debug& debug, ShapeDimensionTraits<2>::Type value) { _val(Box) _val(Composition) #undef _val + /* LCOV_EXCL_STOP */ } - return debug << "Shapes::Shape2D::Type::(unknown)"; + return debug << "Shapes::Shape2D::Type(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, ShapeDimensionTraits<3>::Type value) { switch(value) { + /* LCOV_EXCL_START */ #define _val(value) case ShapeDimensionTraits<3>::Type::value: return debug << "Shapes::Shape3D::Type::" #value; _val(Point) _val(Line) @@ -63,9 +66,10 @@ Debug& operator<<(Debug& debug, ShapeDimensionTraits<3>::Type value) { _val(Plane) _val(Composition) #undef _val + /* LCOV_EXCL_STOP */ } - return debug << "Shapes::Shape3D::Type::(unknown)"; + return debug << "Shapes::Shape3D::Type(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } template AbstractShape::~AbstractShape() = default; diff --git a/src/Magnum/Test/AbstractOpenGLTester.h b/src/Magnum/Test/AbstractOpenGLTester.h index 9e2450d57..ef84d20bd 100644 --- a/src/Magnum/Test/AbstractOpenGLTester.h +++ b/src/Magnum/Test/AbstractOpenGLTester.h @@ -38,8 +38,12 @@ #include "Magnum/Platform/WindowlessIosApplication.h" #elif defined(CORRADE_TARGET_APPLE) #include "Magnum/Platform/WindowlessCglApplication.h" -#elif defined(CORRADE_TARGET_UNIX) && (!defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_DESKTOP_GLES)) +#elif defined(CORRADE_TARGET_UNIX) +#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_DESKTOP_GLES) +#include "Magnum/Platform/WindowlessEglApplication.h" +#else #include "Magnum/Platform/WindowlessGlxApplication.h" +#endif #elif defined(CORRADE_TARGET_WINDOWS) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_DESKTOP_GLES) #include "Magnum/Platform/WindowlessWglApplication.h" @@ -61,7 +65,7 @@ class AbstractOpenGLTester: public TestSuite::Tester { private: struct WindowlessApplication: Platform::WindowlessApplication { - explicit WindowlessApplication(const Arguments& arguments): Platform::WindowlessApplication{arguments, nullptr} {} + explicit WindowlessApplication(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {} int exec() override final { return 0; } using Platform::WindowlessApplication::tryCreateContext; @@ -94,31 +98,7 @@ std::optional AbstractOpenGLTester:: #define MAGNUM_VERIFY_NO_ERROR() CORRADE_COMPARE(Magnum::Renderer::error(), Magnum::Renderer::Error::NoError) -#ifdef CORRADE_TARGET_WINDOWS -#define MAGNUM_GL_TEST_MAIN(Class) \ - LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); \ - LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { \ - int ret = 0; \ - switch(message) { \ - case WM_CREATE: \ - { \ - Magnum::Test::AbstractOpenGLTester::_windowlessApplicationArguments->window = hWnd; \ - Class t; \ - t.registerTest(__FILE__, #Class); \ - PostQuitMessage(ret = t.exec( \ - Magnum::Test::AbstractOpenGLTester::_windowlessApplicationArguments->argc, \ - Magnum::Test::AbstractOpenGLTester::_windowlessApplicationArguments->argv)); \ - } \ - break; \ - default: return DefWindowProc(hWnd, message, wParam, lParam); \ - } \ - return ret; \ - } \ - int main(int argc, char** argv) { \ - Magnum::Test::AbstractOpenGLTester::_windowlessApplicationArguments.emplace(argc, argv, nullptr); \ - return Magnum::Platform::WindowlessApplication::create(windowProcedure); \ - } -#elif defined(CORRADE_TESTSUITE_TARGET_XCTEST) +#ifdef CORRADE_TESTSUITE_TARGET_XCTEST #define MAGNUM_GL_TEST_MAIN(Class) \ int CORRADE_VISIBILITY_EXPORT corradeTestMain(int argc, char** argv) { \ Magnum::Test::AbstractOpenGLTester::_windowlessApplicationArguments.emplace(argc, argv); \ diff --git a/src/Magnum/Test/AbstractShaderProgramGLTest.cpp b/src/Magnum/Test/AbstractShaderProgramGLTest.cpp index 5edeb0b12..d8f29e80c 100644 --- a/src/Magnum/Test/AbstractShaderProgramGLTest.cpp +++ b/src/Magnum/Test/AbstractShaderProgramGLTest.cpp @@ -711,7 +711,7 @@ void AbstractShaderProgramGLTest::compute() { /** @todo Test on ES */ #ifndef MAGNUM_TARGET_GLES - const auto data = out.image(0, {PixelFormat::RGBAInteger, PixelType::UnsignedByte}).data(); + const auto data = out.image(0, {PixelFormat::RGBAInteger, PixelType::UnsignedByte}).release(); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/AbstractShaderProgramTest.cpp b/src/Magnum/Test/AttributeTest.cpp similarity index 57% rename from src/Magnum/Test/AbstractShaderProgramTest.cpp rename to src/Magnum/Test/AttributeTest.cpp index 089b0f573..7c2a5e709 100644 --- a/src/Magnum/Test/AbstractShaderProgramTest.cpp +++ b/src/Magnum/Test/AttributeTest.cpp @@ -23,14 +23,15 @@ DEALINGS IN THE SOFTWARE. */ +#include #include #include "Magnum/AbstractShaderProgram.h" namespace Magnum { namespace Test { -struct AbstractShaderProgramTest: TestSuite::Tester { - explicit AbstractShaderProgramTest(); +struct AttributeTest: TestSuite::Tester { + explicit AttributeTest(); void attributeScalar(); void attributeScalarInt(); @@ -50,30 +51,70 @@ struct AbstractShaderProgramTest: TestSuite::Tester { #endif void attributeMatrixNxNd(); void attributeMatrixMxNd(); + + void debugComponents1(); + void debugComponents2(); + void debugComponents3(); + #ifndef MAGNUM_TARGET_GLES2 + void debugComponents4(); + #endif + void debugComponentsMatrix2(); + void debugComponentsMatrix3(); + void debugComponentsMatrix4(); + void debugComponentsVector4(); + void debugDataTypeFloat(); + #ifndef MAGNUM_TARGET_GLES2 + void debugDataTypeInt(); + #endif + #ifndef MAGNUM_TARGET_GLES + void debugDataTypeDouble(); + #endif + void debugDataTypeVector3(); + void debugDataTypeVector4(); }; -AbstractShaderProgramTest::AbstractShaderProgramTest() { - addTests({&AbstractShaderProgramTest::attributeScalar, - &AbstractShaderProgramTest::attributeScalarInt, - &AbstractShaderProgramTest::attributeScalarUnsignedInt, - &AbstractShaderProgramTest::attributeScalarDouble, +AttributeTest::AttributeTest() { + addTests({&AttributeTest::attributeScalar, + &AttributeTest::attributeScalarInt, + &AttributeTest::attributeScalarUnsignedInt, + &AttributeTest::attributeScalarDouble, - &AbstractShaderProgramTest::attributeVector, - &AbstractShaderProgramTest::attributeVectorInt, - &AbstractShaderProgramTest::attributeVectorUnsignedInt, - &AbstractShaderProgramTest::attributeVectorDouble, - &AbstractShaderProgramTest::attributeVector4, - &AbstractShaderProgramTest::attributeVectorBGRA, + &AttributeTest::attributeVector, + &AttributeTest::attributeVectorInt, + &AttributeTest::attributeVectorUnsignedInt, + &AttributeTest::attributeVectorDouble, + &AttributeTest::attributeVector4, + &AttributeTest::attributeVectorBGRA, - &AbstractShaderProgramTest::attributeMatrixNxN, + &AttributeTest::attributeMatrixNxN, #ifndef MAGNUM_TARGET_GLES2 - &AbstractShaderProgramTest::attributeMatrixMxN, + &AttributeTest::attributeMatrixMxN, #endif - &AbstractShaderProgramTest::attributeMatrixNxNd, - &AbstractShaderProgramTest::attributeMatrixMxNd}); + &AttributeTest::attributeMatrixNxNd, + &AttributeTest::attributeMatrixMxNd, + + &AttributeTest::debugComponents1, + &AttributeTest::debugComponents2, + &AttributeTest::debugComponents3, + #ifndef MAGNUM_TARGET_GLES2 + &AttributeTest::debugComponents4, + #endif + &AttributeTest::debugComponentsMatrix2, + &AttributeTest::debugComponentsMatrix3, + &AttributeTest::debugComponentsMatrix4, + &AttributeTest::debugComponentsVector4, + &AttributeTest::debugDataTypeFloat, + #ifndef MAGNUM_TARGET_GLES + &AttributeTest::debugDataTypeInt, + #endif + #ifndef MAGNUM_TARGET_GLES + &AttributeTest::debugDataTypeDouble, + #endif + &AttributeTest::debugDataTypeVector3, + &AttributeTest::debugDataTypeVector4}); } -void AbstractShaderProgramTest::attributeScalar() { +void AttributeTest::attributeScalar() { typedef Attribute<3, Float> Attribute; CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::Location, 3); @@ -92,7 +133,7 @@ void AbstractShaderProgramTest::attributeScalar() { CORRADE_VERIFY(b.dataOptions() <= Attribute::DataOption::Normalized); } -void AbstractShaderProgramTest::attributeScalarInt() { +void AttributeTest::attributeScalarInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<3, Int> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -110,7 +151,7 @@ void AbstractShaderProgramTest::attributeScalarInt() { #endif } -void AbstractShaderProgramTest::attributeScalarUnsignedInt() { +void AttributeTest::attributeScalarUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<3, UnsignedInt> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -128,7 +169,7 @@ void AbstractShaderProgramTest::attributeScalarUnsignedInt() { #endif } -void AbstractShaderProgramTest::attributeScalarDouble() { +void AttributeTest::attributeScalarDouble() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Double> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -142,7 +183,7 @@ void AbstractShaderProgramTest::attributeScalarDouble() { #endif } -void AbstractShaderProgramTest::attributeVector() { +void AttributeTest::attributeVector() { typedef Attribute<3, Vector3> Attribute; CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); @@ -165,7 +206,7 @@ void AbstractShaderProgramTest::attributeVector() { #endif } -void AbstractShaderProgramTest::attributeVectorInt() { +void AttributeTest::attributeVectorInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<3, Vector2i> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -185,7 +226,7 @@ void AbstractShaderProgramTest::attributeVectorInt() { #endif } -void AbstractShaderProgramTest::attributeVectorUnsignedInt() { +void AttributeTest::attributeVectorUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<3, Vector4ui> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -205,7 +246,7 @@ void AbstractShaderProgramTest::attributeVectorUnsignedInt() { #endif } -void AbstractShaderProgramTest::attributeVectorDouble() { +void AttributeTest::attributeVectorDouble() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Vector2d> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -225,7 +266,7 @@ void AbstractShaderProgramTest::attributeVectorDouble() { #endif } -void AbstractShaderProgramTest::attributeVector4() { +void AttributeTest::attributeVector4() { typedef Attribute<3, Vector4> Attribute; CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); @@ -240,7 +281,7 @@ void AbstractShaderProgramTest::attributeVector4() { #endif } -void AbstractShaderProgramTest::attributeVectorBGRA() { +void AttributeTest::attributeVectorBGRA() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Vector4> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -254,7 +295,7 @@ void AbstractShaderProgramTest::attributeVectorBGRA() { #endif } -void AbstractShaderProgramTest::attributeMatrixNxN() { +void AttributeTest::attributeMatrixNxN() { typedef Attribute<3, Matrix3> Attribute; CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 3); @@ -267,7 +308,7 @@ void AbstractShaderProgramTest::attributeMatrixNxN() { } #ifndef MAGNUM_TARGET_GLES2 -void AbstractShaderProgramTest::attributeMatrixMxN() { +void AttributeTest::attributeMatrixMxN() { typedef Attribute<3, Matrix3x4> Attribute; CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 3); @@ -280,7 +321,7 @@ void AbstractShaderProgramTest::attributeMatrixMxN() { } #endif -void AbstractShaderProgramTest::attributeMatrixNxNd() { +void AttributeTest::attributeMatrixNxNd() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Matrix4d> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -296,7 +337,7 @@ void AbstractShaderProgramTest::attributeMatrixNxNd() { #endif } -void AbstractShaderProgramTest::attributeMatrixMxNd() { +void AttributeTest::attributeMatrixMxNd() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Matrix4x2d> Attribute; CORRADE_VERIFY((std::is_same{})); @@ -312,6 +353,116 @@ void AbstractShaderProgramTest::attributeMatrixMxNd() { #endif } +void AttributeTest::debugComponents1() { + typedef Attribute<3, Float> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::One << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::One Attribute::Components(0xdead)\n"); +} + +void AttributeTest::debugComponents2() { + typedef Attribute<3, Vector2> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::Two << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::Two Attribute::Components(0xdead)\n"); +} + +void AttributeTest::debugComponents3() { + typedef Attribute<3, Vector3> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::Three << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::Three Attribute::Components(0xdead)\n"); +} + +#ifndef MAGNUM_TARGET_GLES2 +void AttributeTest::debugComponents4() { + typedef Attribute<3, Vector4i> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::Four << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::Four Attribute::Components(0xdead)\n"); +} +#endif + +void AttributeTest::debugComponentsMatrix2() { + typedef Attribute<3, Matrix2x2> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::Two << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::Two Attribute::Components(0xdead)\n"); +} + +void AttributeTest::debugComponentsMatrix3() { + typedef Attribute<3, Matrix3> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::Three << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::Three Attribute::Components(0xdead)\n"); +} + +void AttributeTest::debugComponentsMatrix4() { + typedef Attribute<3, Matrix4> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::Four << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::Four Attribute::Components(0xdead)\n"); +} + +void AttributeTest::debugComponentsVector4() { + typedef Attribute<3, Vector4> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::Components::Three << Attribute::Components(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::Components::Three Attribute::Components(0xdead)\n"); +} + +void AttributeTest::debugDataTypeFloat() { + typedef Attribute<3, Float> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::DataType::HalfFloat << Attribute::DataType(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::DataType::HalfFloat Attribute::DataType(0xdead)\n"); +} + +#ifndef MAGNUM_TARGET_GLES2 +void AttributeTest::debugDataTypeInt() { + typedef Attribute<3, Int> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::DataType::Short << Attribute::DataType(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::DataType::Short Attribute::DataType(0xdead)\n"); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void AttributeTest::debugDataTypeDouble() { + typedef Attribute<3, Double> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::DataType::Double << Attribute::DataType(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::DataType::Double Attribute::DataType(0xdead)\n"); +} +#endif + +void AttributeTest::debugDataTypeVector3() { + typedef Attribute<3, Vector3> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::DataType::HalfFloat << Attribute::DataType(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::DataType::HalfFloat Attribute::DataType(0xdead)\n"); +} + +void AttributeTest::debugDataTypeVector4() { + typedef Attribute<3, Vector4> Attribute; + + std::ostringstream out; + Debug{&out} << Attribute::DataType::HalfFloat << Attribute::DataType(0xdead); + CORRADE_COMPARE(out.str(), "Attribute::DataType::HalfFloat Attribute::DataType(0xdead)\n"); +} + }} -CORRADE_TEST_MAIN(Magnum::Test::AbstractShaderProgramTest) +CORRADE_TEST_MAIN(Magnum::Test::AttributeTest) diff --git a/src/Magnum/Test/BufferTest.cpp b/src/Magnum/Test/BufferTest.cpp new file mode 100644 index 000000000..f890f6485 --- /dev/null +++ b/src/Magnum/Test/BufferTest.cpp @@ -0,0 +1,67 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2015 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Magnum/Buffer.h" + +namespace Magnum { namespace Test { + +struct BufferTest: TestSuite::Tester { + explicit BufferTest(); + + void debugTargetHint(); + #ifndef MAGNUM_TARGET_GLES2 + void debugTarget(); + #endif +}; + +BufferTest::BufferTest() { + addTests({&BufferTest::debugTargetHint, + #ifndef MAGNUM_TARGET_GLES2 + &BufferTest::debugTarget + #endif + }); +} + +void BufferTest::debugTargetHint() { + std::ostringstream out; + Debug{&out} << Buffer::TargetHint::Array << Buffer::TargetHint(0xdead); + CORRADE_COMPARE(out.str(), "Buffer::TargetHint::Array Buffer::TargetHint(0xdead)\n"); +} + +#ifndef MAGNUM_TARGET_GLES2 +void BufferTest::debugTarget() { + std::ostringstream out; + Debug{&out} << Buffer::Target::Uniform << Buffer::Target(0xdead); + CORRADE_COMPARE(out.str(), "Buffer::Target::Uniform Buffer::Target(0xdead)\n"); +} +#endif + +}} + +CORRADE_TEST_MAIN(Magnum::Test::BufferTest) diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index a2bca782f..e042bdb67 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -23,11 +23,14 @@ # DEALINGS IN THE SOFTWARE. # -corrade_add_test(AbstractShaderProgramTest AbstractShaderProgramTest.cpp LIBRARIES Magnum) corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum) +corrade_add_test(AttributeTest AttributeTest.cpp LIBRARIES Magnum) +corrade_add_test(BufferTest BufferTest.cpp LIBRARIES Magnum) corrade_add_test(FormatTest FormatTest.cpp LIBRARIES Magnum) corrade_add_test(ContextTest ContextTest.cpp LIBRARIES Magnum) -corrade_add_test(DebugOutputTest DebugOutputTest.cpp LIBRARIES Magnum) +if(NOT MAGNUM_TARGET_WEBGL) + corrade_add_test(DebugOutputTest DebugOutputTest.cpp LIBRARIES Magnum) +endif() corrade_add_test(DefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES Magnum) corrade_add_test(FramebufferTest FramebufferTest.cpp LIBRARIES Magnum) corrade_add_test(ImageTest ImageTest.cpp LIBRARIES Magnum) diff --git a/src/Magnum/Test/ContextTest.cpp b/src/Magnum/Test/ContextTest.cpp index 67d9346bf..bad9274ee 100644 --- a/src/Magnum/Test/ContextTest.cpp +++ b/src/Magnum/Test/ContextTest.cpp @@ -41,9 +41,13 @@ ContextTest::ContextTest() { } void ContextTest::debugFlag() { + #ifdef MAGNUM_TARGET_WEBGL + CORRADE_SKIP("No context flags on Emscripten yet."); + #else std::ostringstream out; - Debug(&out) << Context::Flag::Debug; - CORRADE_COMPARE(out.str(), "Context::Flag::Debug\n"); + Debug(&out) << Context::Flag::Debug << Context::Flag(0xdead); + CORRADE_COMPARE(out.str(), "Context::Flag::Debug Context::Flag(0xdead)\n"); + #endif } }} diff --git a/src/Magnum/Test/DebugOutputTest.cpp b/src/Magnum/Test/DebugOutputTest.cpp index 2d33a04c9..1f9469bfb 100644 --- a/src/Magnum/Test/DebugOutputTest.cpp +++ b/src/Magnum/Test/DebugOutputTest.cpp @@ -56,38 +56,38 @@ DebugOutputTest::DebugOutputTest() { void DebugOutputTest::debugSource() { std::ostringstream o; - Debug(&o) << DebugOutput::Source::ShaderCompiler; - CORRADE_COMPARE(o.str(), "DebugOutput::Source::ShaderCompiler\n"); + Debug(&o) << DebugOutput::Source::ShaderCompiler << DebugOutput::Source(0xdead); + CORRADE_COMPARE(o.str(), "DebugOutput::Source::ShaderCompiler DebugOutput::Source(0xdead)\n"); } void DebugOutputTest::debugType() { std::ostringstream o; - Debug(&o) << DebugOutput::Type::PushGroup; - CORRADE_COMPARE(o.str(), "DebugOutput::Type::PushGroup\n"); + Debug(&o) << DebugOutput::Type::PushGroup << DebugOutput::Type(0xdead); + CORRADE_COMPARE(o.str(), "DebugOutput::Type::PushGroup DebugOutput::Type(0xdead)\n"); } void DebugOutputTest::debugSeverity() { std::ostringstream o; - Debug(&o) << DebugOutput::Severity::Notification; - CORRADE_COMPARE(o.str(), "DebugOutput::Severity::Notification\n"); + Debug(&o) << DebugOutput::Severity::Notification << DebugOutput::Severity(0xdead); + CORRADE_COMPARE(o.str(), "DebugOutput::Severity::Notification DebugOutput::Severity(0xdead)\n"); } void DebugOutputTest::debugMessageSource() { std::ostringstream o; - Debug(&o) << DebugMessage::Source::Application; - CORRADE_COMPARE(o.str(), "DebugMessage::Source::Application\n"); + Debug(&o) << DebugMessage::Source::Application << DebugMessage::Source(0xdead); + CORRADE_COMPARE(o.str(), "DebugMessage::Source::Application DebugMessage::Source(0xdead)\n"); } void DebugOutputTest::debugMessageType() { std::ostringstream o; - Debug(&o) << DebugMessage::Type::DeprecatedBehavior; - CORRADE_COMPARE(o.str(), "DebugMessage::Type::DeprecatedBehavior\n"); + Debug(&o) << DebugMessage::Type::DeprecatedBehavior << DebugMessage::Type(0xdead); + CORRADE_COMPARE(o.str(), "DebugMessage::Type::DeprecatedBehavior DebugMessage::Type(0xdead)\n"); } void DebugOutputTest::debugGroupSource() { std::ostringstream o; - Debug(&o) << DebugGroup::Source::ThirdParty; - CORRADE_COMPARE(o.str(), "DebugGroup::Source::ThirdParty\n"); + Debug(&o) << DebugGroup::Source::ThirdParty << DebugGroup::Source(0xdead); + CORRADE_COMPARE(o.str(), "DebugGroup::Source::ThirdParty DebugGroup::Source(0xdead)\n"); } }} diff --git a/src/Magnum/Test/DefaultFramebufferTest.cpp b/src/Magnum/Test/DefaultFramebufferTest.cpp index 254d5b14c..31c41e5d3 100644 --- a/src/Magnum/Test/DefaultFramebufferTest.cpp +++ b/src/Magnum/Test/DefaultFramebufferTest.cpp @@ -43,8 +43,8 @@ DefaultFramebufferTest::DefaultFramebufferTest() { void DefaultFramebufferTest::debugStatus() { std::ostringstream out; - Debug(&out) << DefaultFramebuffer::Status::Undefined; - CORRADE_COMPARE(out.str(), "DefaultFramebuffer::Status::Undefined\n"); + Debug(&out) << DefaultFramebuffer::Status::Complete << DefaultFramebuffer::Status(0xdead); + CORRADE_COMPARE(out.str(), "DefaultFramebuffer::Status::Complete DefaultFramebuffer::Status(0xdead)\n"); } }} diff --git a/src/Magnum/Test/FormatTest.cpp b/src/Magnum/Test/FormatTest.cpp index 0e58cd210..d1ced28e7 100644 --- a/src/Magnum/Test/FormatTest.cpp +++ b/src/Magnum/Test/FormatTest.cpp @@ -47,15 +47,15 @@ FormatTest::FormatTest() { void FormatTest::debugPixelFormat() { std::ostringstream out; - Debug(&out) << PixelFormat::RGBA; - CORRADE_COMPARE(out.str(), "PixelFormat::RGBA\n"); + Debug(&out) << PixelFormat::RGBA << PixelFormat(0xdead); + CORRADE_COMPARE(out.str(), "PixelFormat::RGBA PixelFormat(0xdead)\n"); } void FormatTest::debugPixelType() { std::ostringstream out; - Debug(&out) << PixelType::UnsignedByte; - CORRADE_COMPARE(out.str(), "PixelType::UnsignedByte\n"); + Debug(&out) << PixelType::UnsignedByte << PixelType(0xdead); + CORRADE_COMPARE(out.str(), "PixelType::UnsignedByte PixelType(0xdead)\n"); } void FormatTest::debugCompressedPixelFormat() { @@ -64,8 +64,8 @@ void FormatTest::debugCompressedPixelFormat() { #else std::ostringstream out; - Debug(&out) << CompressedPixelFormat::RGBBptcUnsignedFloat; - CORRADE_COMPARE(out.str(), "CompressedPixelFormat::RGBBptcUnsignedFloat\n"); + Debug(&out) << CompressedPixelFormat::RGBBptcUnsignedFloat << CompressedPixelFormat(0xdead); + CORRADE_COMPARE(out.str(), "CompressedPixelFormat::RGBBptcUnsignedFloat CompressedPixelFormat(0xdead)\n"); #endif } diff --git a/src/Magnum/Test/FramebufferGLTest.cpp b/src/Magnum/Test/FramebufferGLTest.cpp index fbe32f287..9c9c8a655 100644 --- a/src/Magnum/Test/FramebufferGLTest.cpp +++ b/src/Magnum/Test/FramebufferGLTest.cpp @@ -23,7 +23,8 @@ DEALINGS IN THE SOFTWARE. */ -#include "Magnum/configure.h" +#include + #include "Magnum/Context.h" #include "Magnum/CubeMapTexture.h" #include "Magnum/Extensions.h" @@ -110,6 +111,35 @@ struct FramebufferGLTest: AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void readBuffer(); #endif + #ifndef MAGNUM_TARGET_GLES + void copyImageTexture1D(); + #endif + void copyImageTexture2D(); + #ifndef MAGNUM_TARGET_GLES + void copyImageTexture1DArray(); + #endif + #ifndef MAGNUM_TARGET_GLES + void copyImageRectangleTexture(); + #endif + void copyImageCubeMapTexture(); + #ifndef MAGNUM_TARGET_GLES + void copySubImageTexture1D(); + #endif + void copySubImageTexture2D(); + void copySubImageTexture3D(); + #ifndef MAGNUM_TARGET_GLES + void copySubImageTexture1DArray(); + #endif + #ifndef MAGNUM_TARGET_GLES2 + void copySubImageTexture2DArray(); + #endif + #ifndef MAGNUM_TARGET_GLES + void copySubImageRectangleTexture(); + #endif + void copySubImageCubeMapTexture(); + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + void copySubImageCubeMapTextureArray(); + #endif void blit(); #ifdef MAGNUM_TARGET_GLES2 @@ -175,6 +205,35 @@ FramebufferGLTest::FramebufferGLTest() { #ifndef MAGNUM_TARGET_GLES2 &FramebufferGLTest::readBuffer, #endif + #ifndef MAGNUM_TARGET_GLES + &FramebufferGLTest::copyImageTexture1D, + #endif + &FramebufferGLTest::copyImageTexture2D, + #ifndef MAGNUM_TARGET_GLES + &FramebufferGLTest::copyImageTexture1DArray, + #endif + #ifndef MAGNUM_TARGET_GLES + &FramebufferGLTest::copyImageRectangleTexture, + #endif + &FramebufferGLTest::copyImageCubeMapTexture, + #ifndef MAGNUM_TARGET_GLES + &FramebufferGLTest::copySubImageTexture1D, + #endif + &FramebufferGLTest::copySubImageTexture2D, + &FramebufferGLTest::copySubImageTexture3D, + #ifndef MAGNUM_TARGET_GLES + &FramebufferGLTest::copySubImageTexture1DArray, + #endif + #ifndef MAGNUM_TARGET_GLES2 + &FramebufferGLTest::copySubImageTexture2DArray, + #endif + #ifndef MAGNUM_TARGET_GLES + &FramebufferGLTest::copySubImageRectangleTexture, + #endif + &FramebufferGLTest::copySubImageCubeMapTexture, + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + &FramebufferGLTest::copySubImageCubeMapTextureArray, + #endif &FramebufferGLTest::blit}); #ifdef MAGNUM_TARGET_GLES2 @@ -484,6 +543,8 @@ void FramebufferGLTest::attachTexture3D() { void FramebufferGLTest::attachTexture1DArray() { if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not available.")); Texture1DArray color; color.setStorage(1, TextureFormat::RGBA8, {128, 8}); @@ -888,7 +949,8 @@ void FramebufferGLTest::multipleColorOutputs() { .attachTexture(Framebuffer::ColorAttachment(1), color2, 0) .attachRenderbuffer(Framebuffer::BufferAttachment::Depth, depth) .mapForDraw({{0, Framebuffer::ColorAttachment(1)}, - {1, Framebuffer::ColorAttachment(0)}}); + {1, Framebuffer::ColorAttachment(0)}, + {2, Framebuffer::DrawAttachment::None}}); #ifdef MAGNUM_TARGET_GLES2 if(Context::current().isExtensionSupported()) @@ -1155,6 +1217,501 @@ void FramebufferGLTest::readBuffer() { } #endif +namespace { + constexpr char StorageData[]{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f + }; + + constexpr char ZeroStorage[4*4*4*6]{}; +} + +#ifndef MAGNUM_TARGET_GLES +void FramebufferGLTest::copyImageTexture1D() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture1D texture; + fb.copyImage(Range2Di::fromSize(Vector2i{1}, {2, 1}), texture, 0, TextureFormat::RGBA8); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(0)[0], 2); + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from(0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b), + TestSuite::Compare::Container); +} +#endif + +void FramebufferGLTest::copyImageTexture2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + #endif + + Texture2D storage; + storage.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture2D texture; + fb.copyImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8 + #else + rgbaFormatES2 + #endif + ); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(texture.imageSize(0), Vector2i{2}); + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from(0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b), + TestSuite::Compare::Container); + #endif +} + +#ifndef MAGNUM_TARGET_GLES +void FramebufferGLTest::copyImageTexture1DArray() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not available.")); + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture1DArray texture; + fb.copyImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, TextureFormat::RGBA8); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(0), Vector2i{2}); + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from(0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b), + TestSuite::Compare::Container); +} + +void FramebufferGLTest::copyImageRectangleTexture() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not available.")); + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + RectangleTexture texture; + fb.copyImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, TextureFormat::RGBA8); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(), Vector2i{2}); + CORRADE_COMPARE_AS(texture.image({PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from(0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b), + TestSuite::Compare::Container); +} +#endif + +void FramebufferGLTest::copyImageCubeMapTexture() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + #endif + + Texture2D storage; + storage.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + CubeMapTexture texture; + fb.copyImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, CubeMapCoordinate::PositiveX, 0, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8 + #else + rgbaFormatES2 + #endif + ); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(texture.imageSize(0), Vector2i{2}); + CORRADE_COMPARE_AS(texture.image(CubeMapCoordinate::PositiveX, 0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from(0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b), + TestSuite::Compare::Container); + #endif +} + +#ifndef MAGNUM_TARGET_GLES +void FramebufferGLTest::copySubImageTexture1D() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture1D texture; + texture.setStorage(1, TextureFormat::RGBA8, 4) + .setSubImage(0, {}, ImageView1D{PixelFormat::RGBA, PixelType::UnsignedByte, 4, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, {2, 1}), texture, 0, 1); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); +} +#endif + +void FramebufferGLTest::copySubImageTexture2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + #endif + + Texture2D storage; + storage.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture2D texture; + texture.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, Vector2i{1}); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); + #endif +} + +#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) +void FramebufferGLTest::copySubImageTexture3D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + #elif defined(MAGNUM_TARGET_GLES2) + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not available.")); + #endif + + Texture2D storage; + storage.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture3D texture; + texture.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + {4, 4, 2}) + .setSubImage(0, {}, ImageView3D{PixelFormat::RGBA, PixelType::UnsignedByte, {4, 4, 2}, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, Vector3i{1}); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); + #endif +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void FramebufferGLTest::copySubImageTexture1DArray() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not available.")); + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture1DArray texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, Vector2i{1}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); +} +#endif + +#ifndef MAGNUM_TARGET_GLES2 +void FramebufferGLTest::copySubImageTexture2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not available.")); + #endif + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + Texture2DArray texture; + texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 2}) + .setSubImage(0, {}, ImageView3D{PixelFormat::RGBA, PixelType::UnsignedByte, {4, 4, 2}, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, Vector3i{1}); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); + #endif +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void FramebufferGLTest::copySubImageRectangleTexture() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not available.")); + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + RectangleTexture texture; + texture.setStorage(TextureFormat::RGBA8, Vector2i{4}) + .setSubImage({}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, Vector2i{1}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE_AS(texture.image({PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); +} +#endif + +void FramebufferGLTest::copySubImageCubeMapTexture() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + #endif + + Texture2D storage; + storage.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + CubeMapTexture texture; + texture.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + TextureFormat::RGBA8, + #else + rgbaFormatES2, + #endif + Vector2i{4}) + .setSubImage(CubeMapCoordinate::NegativeY, 0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, {1, 1, 3}); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(texture.image(CubeMapCoordinate::NegativeY, 0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); + #endif +} + +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +void FramebufferGLTest::copySubImageCubeMapTextureArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not available.")); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_cube_map_array::string() + std::string(" is not available.")); + #endif + + Texture2D storage; + storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, StorageData}); + + Framebuffer fb{{{}, Vector2i{4}}}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, storage, 0); + + CubeMapTextureArray texture; + texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 6}) + .setSubImage(0, {}, ImageView3D{PixelFormat::RGBA, PixelType::UnsignedByte, {4, 4, 6}, ZeroStorage}); + fb.copySubImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), texture, 0, {1, 1, 3}); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), + Containers::Array::from( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TestSuite::Compare::Container); + #endif +} +#endif + void FramebufferGLTest::blit() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) diff --git a/src/Magnum/Test/FramebufferTest.cpp b/src/Magnum/Test/FramebufferTest.cpp index 2229721f5..f73180162 100644 --- a/src/Magnum/Test/FramebufferTest.cpp +++ b/src/Magnum/Test/FramebufferTest.cpp @@ -43,8 +43,8 @@ FramebufferTest::FramebufferTest() { void FramebufferTest::debugStatus() { std::ostringstream out; - Debug(&out) << Framebuffer::Status::IncompleteMissingAttachment; - CORRADE_COMPARE(out.str(), "Framebuffer::Status::IncompleteMissingAttachment\n"); + Debug(&out) << Framebuffer::Status::IncompleteMissingAttachment << Framebuffer::Status(0xdead); + CORRADE_COMPARE(out.str(), "Framebuffer::Status::IncompleteMissingAttachment Framebuffer::Status(0xdead)\n"); } }} diff --git a/src/Magnum/Test/ImageTest.cpp b/src/Magnum/Test/ImageTest.cpp index 224855a2f..5f6e9347c 100644 --- a/src/Magnum/Test/ImageTest.cpp +++ b/src/Magnum/Test/ImageTest.cpp @@ -65,12 +65,12 @@ ImageTest::ImageTest() { } void ImageTest::construct() { - auto data = new char[3]; + auto data = new char[3*4]; Image2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3}}; + PixelFormat::RGBA, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*4}}; CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::Red); + CORRADE_COMPARE(a.format(), PixelFormat::RGBA); CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); CORRADE_COMPARE(a.size(), Vector2i(1, 3)); CORRADE_COMPARE(a.data(), data); @@ -104,16 +104,16 @@ void ImageTest::constructCopyCompressed() { } void ImageTest::constructMove() { - auto data = new char[3]; + auto data = new char[3*3]; Image2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3}}; + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; Image2D b(std::move(a)); CORRADE_COMPARE(a.data(), nullptr); CORRADE_COMPARE(a.size(), Vector2i()); CORRADE_COMPARE(b.storage().alignment(), 1); - CORRADE_COMPARE(b.format(), PixelFormat::Red); + CORRADE_COMPARE(b.format(), PixelFormat::RGB); CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.data(), data); @@ -126,7 +126,7 @@ void ImageTest::constructMove() { CORRADE_COMPARE(b.size(), Vector2i(2, 6)); CORRADE_COMPARE(c.storage().alignment(), 1); - CORRADE_COMPARE(c.format(), PixelFormat::Red); + CORRADE_COMPARE(c.format(), PixelFormat::RGB); CORRADE_COMPARE(c.type(), PixelType::UnsignedByte); CORRADE_COMPARE(c.size(), Vector2i(1, 3)); CORRADE_COMPARE(c.data(), data); @@ -170,9 +170,9 @@ void ImageTest::constructMoveCompressed() { } void ImageTest::setData() { - auto data = new char[3]; + auto data = new char[3*3]; Image2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3}}; + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; auto data2 = new char[2*2*4]; a.setData(PixelFormat::RGBA, PixelType::UnsignedShort, {2, 1}, Containers::Array{data2, 2*2*4}); @@ -203,13 +203,13 @@ void ImageTest::setDataCompressed() { } void ImageTest::toView() { - auto data = new char[3]; + auto data = new char[3*3]; const Image2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3}}; + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; ImageView2D b = a; CORRADE_COMPARE(b.storage().alignment(), 1); - CORRADE_COMPARE(b.format(), PixelFormat::Red); + CORRADE_COMPARE(b.format(), PixelFormat::RGB); CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.data(), data); @@ -235,7 +235,7 @@ void ImageTest::toViewCompressed() { void ImageTest::release() { char data[] = {'c', 'a', 'f', 'e'}; - Image2D a(PixelFormat::Red, PixelType::UnsignedByte, {4, 1}, Containers::Array{data, 4}); + Image2D a(PixelFormat::RGBA, PixelType::UnsignedByte, {1, 1}, Containers::Array{data, 4}); const char* const pointer = a.release().release(); CORRADE_COMPARE(pointer, data); diff --git a/src/Magnum/Test/ImageViewTest.cpp b/src/Magnum/Test/ImageViewTest.cpp index 47074ae7f..18e300d3b 100644 --- a/src/Magnum/Test/ImageViewTest.cpp +++ b/src/Magnum/Test/ImageViewTest.cpp @@ -36,8 +36,16 @@ struct ImageViewTest: TestSuite::Tester { void construct(); void constructNullptr(); void constructCompressed(); + #ifdef MAGNUM_BUILD_DEPRECATED + void constructDeprecatedArrayView(); + void constructDeprecatedArray(); + #endif void setData(); + #ifdef MAGNUM_BUILD_DEPRECATED + void setDataDeprecatedArrayView(); + void setDataDeprecatedArray(); + #endif void setDataCompressed(); }; @@ -45,18 +53,26 @@ ImageViewTest::ImageViewTest() { addTests({&ImageViewTest::construct, &ImageViewTest::constructNullptr, &ImageViewTest::constructCompressed, + #ifdef MAGNUM_BUILD_DEPRECATED + &ImageViewTest::constructDeprecatedArrayView, + &ImageViewTest::constructDeprecatedArray, + #endif &ImageViewTest::setData, + #ifdef MAGNUM_BUILD_DEPRECATED + &ImageViewTest::setDataDeprecatedArrayView, + &ImageViewTest::setDataDeprecatedArray, + #endif &ImageViewTest::setDataCompressed}); } void ImageViewTest::construct() { - const char data[3]{}; + const char data[3*3]{}; ImageView2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, data}; + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, data}; CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::Red); + CORRADE_COMPARE(a.format(), PixelFormat::RGB); CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); CORRADE_COMPARE(a.size(), Vector2i(1, 3)); CORRADE_COMPARE(a.data(), data); @@ -85,20 +101,56 @@ void ImageViewTest::constructCompressed() { CORRADE_COMPARE(a.data(), data); } +#ifdef MAGNUM_BUILD_DEPRECATED +void ImageViewTest::constructDeprecatedArrayView() { + const char data[12]{}; + Containers::ArrayView view{data}; + ImageView2D a{PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, view}; + + CORRADE_COMPARE(a.data(), data); +} + +void ImageViewTest::constructDeprecatedArray() { + Containers::Array data{12}; + ImageView2D a{PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, data}; + + CORRADE_COMPARE(a.data(), data); +} +#endif + void ImageViewTest::setData() { - const char data[3]{}; + const char data[3*3]{}; ImageView2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, data}; - const char data2[3]{}; + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, data}; + const char data2[3*3]{}; a.setData(data2); CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::Red); + CORRADE_COMPARE(a.format(), PixelFormat::RGB); CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); CORRADE_COMPARE(a.size(), Vector2i(1, 3)); CORRADE_COMPARE(a.data(), data2); } +#ifdef MAGNUM_BUILD_DEPRECATED +void ImageViewTest::setDataDeprecatedArrayView() { + ImageView2D a{PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, nullptr}; + + const char data[12]{}; + Containers::ArrayView view{data}; + a.setData(view); + CORRADE_COMPARE(a.data(), data); +} + +void ImageViewTest::setDataDeprecatedArray() { + ImageView2D a{PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, nullptr}; + + Containers::Array data{12}; + a.setData(data); + CORRADE_COMPARE(a.data(), data); +} +#endif + void ImageViewTest::setDataCompressed() { const char data[8]{}; CompressedImageView2D a{ diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index 41b4543cc..e798a7423 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -1853,19 +1853,23 @@ MultiChecker::MultiChecker(AbstractShaderProgram&& shader, Mesh& mesh): framebuf mesh.setPrimitive(MeshPrimitive::Points) .setCount(2); + /* Set zero count so we test mesh skipping */ + MeshView a{mesh}; + a.setCount(0); + /* Skip first vertex so we test also offsets */ - MeshView a(mesh); - a.setCount(1) + MeshView b{mesh}; + b.setCount(1) .setBaseVertex(mesh.baseVertex()); - MeshView b(mesh); - b.setCount(1); + MeshView c{mesh}; + c.setCount(1); if(mesh.isIndexed()) { - b.setBaseVertex(mesh.baseVertex()) + c.setBaseVertex(mesh.baseVertex()) .setIndexRange(1); - } else b.setBaseVertex(1); + } else c.setBaseVertex(1); - MeshView::draw(shader, {a, b}); + MeshView::draw(shader, {a, b, c}); } template T MultiChecker::get(PixelFormat format, PixelType type) { diff --git a/src/Magnum/Test/MeshTest.cpp b/src/Magnum/Test/MeshTest.cpp index c4c382a05..9d58b17c6 100644 --- a/src/Magnum/Test/MeshTest.cpp +++ b/src/Magnum/Test/MeshTest.cpp @@ -59,14 +59,14 @@ void MeshTest::indexSize() { void MeshTest::debugPrimitive() { std::ostringstream o; - Debug(&o) << MeshPrimitive::TriangleFan; - CORRADE_COMPARE(o.str(), "MeshPrimitive::TriangleFan\n"); + Debug(&o) << MeshPrimitive::TriangleFan << MeshPrimitive(0xdead); + CORRADE_COMPARE(o.str(), "MeshPrimitive::TriangleFan MeshPrimitive(0xdead)\n"); } void MeshTest::debugIndexType() { std::ostringstream o; - Debug(&o) << Mesh::IndexType::UnsignedShort; - CORRADE_COMPARE(o.str(), "Mesh::IndexType::UnsignedShort\n"); + Debug(&o) << Mesh::IndexType::UnsignedShort << Mesh::IndexType(0xdead); + CORRADE_COMPARE(o.str(), "Mesh::IndexType::UnsignedShort Mesh::IndexType(0xdead)\n"); } void MeshTest::configurationPrimitive() { diff --git a/src/Magnum/Test/PixelStorageTest.cpp b/src/Magnum/Test/PixelStorageTest.cpp index 41f96a356..15de32f0b 100644 --- a/src/Magnum/Test/PixelStorageTest.cpp +++ b/src/Magnum/Test/PixelStorageTest.cpp @@ -38,12 +38,16 @@ struct PixelStorageTest: TestSuite::Tester { void dataProperties(); void dataPropertiesAlignment(); + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void dataPropertiesRowLength(); + #endif #ifndef MAGNUM_TARGET_GLES2 void dataPropertiesImageHeight(); #endif - void dataSize(); + void dataSize1D(); + void dataSize2D(); + void dataSize3D(); #ifndef MAGNUM_TARGET_GLES void dataPropertiesCompressed(); @@ -61,12 +65,16 @@ PixelStorageTest::PixelStorageTest() { &PixelStorageTest::dataProperties, &PixelStorageTest::dataPropertiesAlignment, + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) &PixelStorageTest::dataPropertiesRowLength, + #endif #ifndef MAGNUM_TARGET_GLES2 &PixelStorageTest::dataPropertiesImageHeight, #endif - &PixelStorageTest::dataSize, + &PixelStorageTest::dataSize1D, + &PixelStorageTest::dataSize2D, + &PixelStorageTest::dataSize3D, #ifndef MAGNUM_TARGET_GLES &PixelStorageTest::dataPropertiesCompressed, @@ -81,7 +89,9 @@ PixelStorageTest::PixelStorageTest() { void PixelStorageTest::pixelSize() { CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::RGBA, PixelType::UnsignedInt), 4*4); CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::DepthComponent, PixelType::UnsignedShort), 2); + #ifndef MAGNUM_TARGET_WEBGL CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::StencilIndex, PixelType::UnsignedByte), 1); + #endif CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::DepthStencil, PixelType::UnsignedInt248), 4); } @@ -90,15 +100,17 @@ void PixelStorageTest::dataProperties() { storage.setAlignment(1); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{0, {0, 0, 0}, 4})); + (std::tuple{{}, {0, 0, 0}, 4})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{0, {4, 1, 1}, 4})); + (std::tuple{{}, {4, 1, 1}, 4})); + #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}), - (std::tuple{0, {8, 2, 1}, 1})); + (std::tuple{{}, {8, 2, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{0, {2, 4, 1}, 1})); + (std::tuple{{}, {2, 4, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{0, {2, 4, 6}, 1})); + (std::tuple{{}, {2, 4, 6}, 1})); + #endif } void PixelStorageTest::dataPropertiesAlignment() { @@ -107,17 +119,20 @@ void PixelStorageTest::dataPropertiesAlignment() { .setSkip({3, 2, 1}); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{3*4, {0, 0, 0}, 4})); + (std::tuple{{3*4, 0, 0}, {0, 0, 0}, 4})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{8 + 16 + 3*4, {8, 1, 1}, 4})); + (std::tuple{{12, 16, 8}, {8, 1, 1}, 4})); + #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}), - (std::tuple{16 + 16 + 3, {8, 2, 1}, 1})); + (std::tuple{{3, 16, 16}, {8, 2, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{32 + 16 + 3, {8, 4, 1}, 1})); + (std::tuple{{3, 16, 32}, {8, 4, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{32 + 16 + 3, {8, 4, 6}, 1})); + (std::tuple{{3, 16, 32}, {8, 4, 6}, 1})); + #endif } +#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void PixelStorageTest::dataPropertiesRowLength() { PixelStorage storage; storage.setAlignment(4) @@ -125,16 +140,17 @@ void PixelStorageTest::dataPropertiesRowLength() { .setSkip({3, 7, 0}); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{3*4 + 7*15*4, {0, 0, 0}, 4})); + (std::tuple{{3*4, 7*15*4, 0}, {0, 0, 0}, 4})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{3*4 + 7*15*4, {60, 1, 1}, 4})); + (std::tuple{{3*4, 7*15*4, 0}, {60, 1, 1}, 4})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}), - (std::tuple{3 + 7*16, {16, 2, 1}, 1})); + (std::tuple{{3, 7*16, 0}, {16, 2, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{3 + 7*16, {16, 4, 1}, 1})); + (std::tuple{{3, 7*16, 0}, {16, 4, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{3 + 7*16, {16, 4, 6}, 1})); + (std::tuple{{3, 7*16, 0}, {16, 4, 6}, 1})); } +#endif #ifndef MAGNUM_TARGET_GLES2 void PixelStorageTest::dataPropertiesImageHeight() { @@ -144,34 +160,98 @@ void PixelStorageTest::dataPropertiesImageHeight() { .setSkip({3, 7, 2}); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{3*4, {0, 0, 0}, 4})); + (std::tuple{{3*4, 0, 0}, {0, 0, 0}, 4})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{3*4 + 7*1*4 + 2*128*1*4, {4, 128, 1}, 4})); + (std::tuple{{3*4, 7*1*4, 2*128*1*4}, {4, 128, 1}, 4})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}), - (std::tuple{3 + 7*1*4 + 2*128*4, {4, 128, 1}, 1})); + (std::tuple{{3, 7*1*4, 2*128*4}, {4, 128, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{3 + 7*1*2 + 2*128*2, {2, 128, 1}, 1})); + (std::tuple{{3, 7*1*2, 2*128*2}, {2, 128, 1}, 1})); CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{3 + 7*1*2 + 2*128*2, {2, 128, 6}, 1})); + (std::tuple{{3, 7*1*2, 2*128*2}, {2, 128, 6}, 1})); } #endif -void PixelStorageTest::dataSize() { - /* The same parameters as in PixelStorageGLTest 3D case */ +void PixelStorageTest::dataSize1D() { + const Image1D image{PixelStorage{}.setAlignment(2) + .setSkip({2, 0, 0}), + PixelFormat::RGB, PixelType::UnsignedByte}; + + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Math::Vector<1, Int>{3}), + 16); +} + +void PixelStorageTest::dataSize2D() { const Image2D image{PixelStorage{}.setAlignment(2) - .setRowLength(3) + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + .setRowLength(7) + #endif + .setSkip({2, 3, 0}), + PixelFormat::RGB, PixelType::UnsignedByte}; + + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{5, 9}), + (3 + 9)*16); + #else + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{5, 9}), + (3 + 9)*22); + #endif + + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + /* This shouldn't overflow the 128x128 rectangle */ + const Image2D image2{PixelStorage{}.setSkip({64, 0, 0}) + .setRowLength(128), + PixelFormat::RGBA, PixelType::UnsignedByte}; + + CORRADE_COMPARE(Implementation::imageDataSizeFor(image2, Vector2i{64, 128}), 65536); + + /* This shouldn't overflow the 128x128 rectangle */ + const Image2D image3{PixelStorage{}.setSkip({64, 64, 0}) + .setRowLength(128), + PixelFormat::RGBA, PixelType::UnsignedByte}; + + CORRADE_COMPARE(Implementation::imageDataSizeFor(image3, Vector2i{64, 64}), 65536); + #endif +} + +void PixelStorageTest::dataSize3D() { + const Image3D image{PixelStorage{}.setAlignment(2) + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + .setRowLength(7) + #endif #ifndef MAGNUM_TARGET_GLES2 - .setImageHeight(5) + .setImageHeight(10) #endif .setSkip({2, 3, 1}), PixelFormat::RGB, PixelType::UnsignedByte}; - #ifndef MAGNUM_TARGET_GLES2 - CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{2, 3}), - 5*10 + 3*10 + 6 + 3*10); + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}), + (1 + 3)*9*16); + #elif defined(MAGNUM_TARGET_GLES2) + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}), + (1 + 3)*9*22); #else - CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{2, 3}), - 3*10 + 3*10 + 6 + 3*10); + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}), + (1 + 3)*10*22); + #endif + + #ifndef MAGNUM_TARGET_GLES2 + /* This shouldn't overflow the 128x128x128 cube */ + const Image3D image2{PixelStorage{}.setSkip({64, 64, 0}) + .setRowLength(128) + .setImageHeight(128), + PixelFormat::RGBA, PixelType::UnsignedByte}; + + CORRADE_COMPARE(Implementation::imageDataSizeFor(image2, Vector3i{64, 64, 128}), 8388608); + + /* This shouldn't overflow the 128x128x128 cube */ + const Image3D image3{PixelStorage{}.setSkip({64, 64, 64}) + .setRowLength(128) + .setImageHeight(128), + PixelFormat::RGBA, PixelType::UnsignedByte}; + + CORRADE_COMPARE(Implementation::imageDataSizeFor(image3, Vector3i{64, 64, 64}), 8388608); #endif } @@ -182,7 +262,7 @@ void PixelStorageTest::dataPropertiesCompressed() { .setCompressedBlockDataSize(16); CORRADE_COMPARE(storage.dataProperties({2, 8, 11}), - (std::tuple{0, {1, 2, 3}, 16})); + (std::tuple{{}, {1, 2, 3}, 16})); } void PixelStorageTest::dataPropertiesCompressedRowLength() { @@ -193,7 +273,7 @@ void PixelStorageTest::dataPropertiesCompressedRowLength() { .setSkip({5, 8, 0}); CORRADE_COMPARE(storage.dataProperties({2, 8, 11}), - (std::tuple{(2 + 8)*9, {4, 2, 3}, 9})); + (std::tuple{{2*9, 8*9, 0}, {4, 2, 3}, 9})); } void PixelStorageTest::dataPropertiesCompressedImageHeight() { @@ -204,7 +284,7 @@ void PixelStorageTest::dataPropertiesCompressedImageHeight() { .setSkip({5, 8, 11}); CORRADE_COMPARE(storage.dataProperties({2, 8, 11}), - (std::tuple{(2 + 2 + 9)*16, {1, 3, 3}, 16})); + (std::tuple{{2*16, 2*16, 9*16}, {1, 3, 3}, 16})); } void PixelStorageTest::dataOffsetSizeCompressed() { diff --git a/src/Magnum/Test/PrimitiveQueryGLTest.cpp b/src/Magnum/Test/PrimitiveQueryGLTest.cpp index 3c63d9527..ae2881894 100644 --- a/src/Magnum/Test/PrimitiveQueryGLTest.cpp +++ b/src/Magnum/Test/PrimitiveQueryGLTest.cpp @@ -48,8 +48,12 @@ struct PrimitiveQueryGLTest: AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES void primitivesGenerated(); + void primitivesGeneratedIndexed(); #endif void transformFeedbackPrimitivesWritten(); + #ifndef MAGNUM_TARGET_GLES + void transformFeedbackOverflow(); + #endif }; PrimitiveQueryGLTest::PrimitiveQueryGLTest() { @@ -58,8 +62,13 @@ PrimitiveQueryGLTest::PrimitiveQueryGLTest() { #ifndef MAGNUM_TARGET_GLES &PrimitiveQueryGLTest::primitivesGenerated, + &PrimitiveQueryGLTest::primitivesGeneratedIndexed, #endif - &PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten}); + &PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten, + #ifndef MAGNUM_TARGET_GLES + &PrimitiveQueryGLTest::transformFeedbackOverflow + #endif + }); } void PrimitiveQueryGLTest::constructNoCreate() { @@ -158,6 +167,67 @@ void PrimitiveQueryGLTest::primitivesGenerated() { CORRADE_VERIFY(availableAfter); CORRADE_COMPARE(count, 3); } + +void PrimitiveQueryGLTest::primitivesGeneratedIndexed() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::transform_feedback3::string() + std::string(" is not available.")); + + /* Bind some FB to avoid errors on contexts w/o default FB */ + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, Vector2i{32}); + Framebuffer fb{{{}, Vector2i{32}}}; + fb.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color) + .bind(); + + struct MyShader: AbstractShaderProgram { + typedef Attribute<0, Vector2> Position; + + explicit MyShader() { + Shader vert( + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + , Shader::Type::Vertex); + + CORRADE_INTERNAL_ASSERT_OUTPUT(vert.addSource( + "#if __VERSION__ >= 130\n" + "#define attribute in\n" + "#endif\n" + "attribute vec4 position;\n" + "void main() {\n" + " gl_Position = position;\n" + "}\n").compile()); + + attachShader(vert); + bindAttributeLocation(Position::Location, "position"); + CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + } + } shader; + + Buffer vertices; + vertices.setData({nullptr, 9*sizeof(Vector2)}, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setPrimitive(MeshPrimitive::Triangles) + .setCount(9) + .addVertexBuffer(vertices, 0, MyShader::Position()); + + MAGNUM_VERIFY_NO_ERROR(); + + PrimitiveQuery q{PrimitiveQuery::Target::PrimitivesGenerated}; + q.begin(0); + + Renderer::enable(Renderer::Feature::RasterizerDiscard); + mesh.draw(shader); + + q.end(); + const UnsignedInt count = q.result(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(count, 3); +} #endif void PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten() { @@ -210,7 +280,7 @@ void PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten() { } shader; Buffer output; - output.setData({nullptr, 18*sizeof(Vector2)}, BufferUsage::StaticDraw); + output.setData({nullptr, 9*sizeof(Vector2)}, BufferUsage::StaticDraw); Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) @@ -238,6 +308,91 @@ void PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten() { CORRADE_COMPARE(count, 3); /* Three triangles (9 vertices) */ } +#ifndef MAGNUM_TARGET_GLES +void PrimitiveQueryGLTest::transformFeedbackOverflow() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::transform_feedback_overflow_query::string() + std::string(" is not available.")); + #endif + + /* Bind some FB to avoid errors on contexts w/o default FB */ + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, Vector2i{32}); + Framebuffer fb{{{}, Vector2i{32}}}; + fb.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color) + .bind(); + + struct MyShader: AbstractShaderProgram { + explicit MyShader() { + #ifndef MAGNUM_TARGET_GLES + Shader vert( + #ifndef CORRADE_TARGET_APPLE + Version::GL300 + #else + Version::GL310 + #endif + , Shader::Type::Vertex); + #else + Shader vert(Version::GLES300, Shader::Type::Vertex); + Shader frag(Version::GLES300, Shader::Type::Fragment); + #endif + + CORRADE_INTERNAL_ASSERT_OUTPUT(vert.addSource( + "out mediump vec2 outputData;\n" + "void main() {\n" + " outputData = vec2(1.0, -1.0);\n" + /* Mesa drivers complain that vertex shader doesn't write to + gl_Position otherwise */ + " gl_Position = vec4(1.0);\n" + "}\n").compile()); + #ifndef MAGNUM_TARGET_GLES + attachShader(vert); + #else + /* ES for some reason needs both vertex and fragment shader */ + CORRADE_INTERNAL_ASSERT_OUTPUT(frag.addSource("void main() {}\n").compile()); + attachShaders({vert, frag}); + #endif + + setTransformFeedbackOutputs({"outputData"}, TransformFeedbackBufferMode::SeparateAttributes); + CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + } + } shader; + + Buffer output; + output.setData({nullptr, 18*sizeof(Vector2)}, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setPrimitive(MeshPrimitive::Triangles) + .setCount(9); + + MAGNUM_VERIFY_NO_ERROR(); + + TransformFeedback feedback; + /* Deliberately one vertex smaller to not fit two of them */ + feedback.attachBuffer(0, output, 0, 17*sizeof(Vector2)); + + Renderer::enable(Renderer::Feature::RasterizerDiscard); + + feedback.begin(shader, TransformFeedback::PrimitiveMode::Triangles); + PrimitiveQuery q1{PrimitiveQuery::Target::TransformFeedbackOverflow}, + q2{PrimitiveQuery::Target::TransformFeedbackOverflow}; + q1.begin(); + mesh.draw(shader); + q1.end(); + q2.begin(); + mesh.draw(shader); + q2.end(); + feedback.end(); + + const bool overflown1 = q1.result(); + const bool overflown2 = q2.result(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(!overflown1); + CORRADE_VERIFY(overflown2); /* Got space for only 17 vertices instead of 2*9 */ +} +#endif + }} MAGNUM_GL_TEST_MAIN(Magnum::Test::PrimitiveQueryGLTest) diff --git a/src/Magnum/Test/RendererTest.cpp b/src/Magnum/Test/RendererTest.cpp index 5aaa689c5..6c7665162 100644 --- a/src/Magnum/Test/RendererTest.cpp +++ b/src/Magnum/Test/RendererTest.cpp @@ -34,34 +34,43 @@ struct RendererTest: TestSuite::Tester { explicit RendererTest(); void debugError(); + #ifndef MAGNUM_TARGET_WEBGL void debugResetNotificationStrategy(); void debugGraphicsResetStatus(); + #endif }; RendererTest::RendererTest() { - addTests({&RendererTest::debugError}); + addTests({&RendererTest::debugError, + #ifndef MAGNUM_TARGET_WEBGL + &RendererTest::debugResetNotificationStrategy, + &RendererTest::debugGraphicsResetStatus + #endif + }); } void RendererTest::debugError() { std::ostringstream out; - Debug(&out) << Renderer::Error::InvalidOperation; - CORRADE_COMPARE(out.str(), "Renderer::Error::InvalidOperation\n"); + Debug(&out) << Renderer::Error::InvalidOperation << Renderer::Error(0xdead); + CORRADE_COMPARE(out.str(), "Renderer::Error::InvalidOperation Renderer::Error(0xdead)\n"); } +#ifndef MAGNUM_TARGET_WEBGL void RendererTest::debugResetNotificationStrategy() { std::ostringstream out; - Debug(&out) << Renderer::ResetNotificationStrategy::LoseContextOnReset; - CORRADE_COMPARE(out.str(), "Renderer::ResetNotificationStrategy::LoseContextOnReset\n"); + Debug(&out) << Renderer::ResetNotificationStrategy::LoseContextOnReset << Renderer::ResetNotificationStrategy(0xdead); + CORRADE_COMPARE(out.str(), "Renderer::ResetNotificationStrategy::LoseContextOnReset Renderer::ResetNotificationStrategy(0xdead)\n"); } void RendererTest::debugGraphicsResetStatus() { std::ostringstream out; - Debug(&out) << Renderer::GraphicsResetStatus::GuiltyContextReset; - CORRADE_COMPARE(out.str(), "Renderer::GraphicsResetStatus::GuiltyContextReset\n"); + Debug(&out) << Renderer::GraphicsResetStatus::GuiltyContextReset << Renderer::GraphicsResetStatus(0xdead); + CORRADE_COMPARE(out.str(), "Renderer::GraphicsResetStatus::GuiltyContextReset Renderer::GraphicsResetStatus(0xdead)\n"); } +#endif }} diff --git a/src/Magnum/Test/ResourceManagerTest.cpp b/src/Magnum/Test/ResourceManagerTest.cpp index d746901cf..c35b07ffe 100644 --- a/src/Magnum/Test/ResourceManagerTest.cpp +++ b/src/Magnum/Test/ResourceManagerTest.cpp @@ -45,6 +45,8 @@ struct ResourceManagerTest: TestSuite::Tester { void clear(); void clearWhileReferenced(); void loader(); + + void debugResourceState(); }; struct Data { @@ -69,7 +71,9 @@ ResourceManagerTest::ResourceManagerTest() { &ResourceManagerTest::defaults, &ResourceManagerTest::clear, &ResourceManagerTest::clearWhileReferenced, - &ResourceManagerTest::loader}); + &ResourceManagerTest::loader, + + &ResourceManagerTest::debugResourceState}); } void ResourceManagerTest::state() { @@ -326,6 +330,12 @@ void ResourceManagerTest::loader() { CORRADE_COMPARE(Data::count, 0); } +void ResourceManagerTest::debugResourceState() { + std::ostringstream out; + Debug{&out} << ResourceState::Loading << ResourceState(0xbe); + CORRADE_COMPARE(out.str(), "ResourceState::Loading ResourceState(0xbe)\n"); +} + }} CORRADE_TEST_MAIN(Magnum::Test::ResourceManagerTest) diff --git a/src/Magnum/Test/SamplerTest.cpp b/src/Magnum/Test/SamplerTest.cpp index 621edffde..0d686aee1 100644 --- a/src/Magnum/Test/SamplerTest.cpp +++ b/src/Magnum/Test/SamplerTest.cpp @@ -36,8 +36,10 @@ struct SamplerTest: TestSuite::Tester { void debugFilter(); void debugMipmap(); void debugWrapping(); + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void debugCompareMode(); void debugCompareFunction(); + #endif #ifndef MAGNUM_TARGET_GLES void debugDepthStencilMode(); #endif @@ -47,8 +49,10 @@ SamplerTest::SamplerTest() { addTests({&SamplerTest::debugFilter, &SamplerTest::debugMipmap, &SamplerTest::debugWrapping, + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) &SamplerTest::debugCompareMode, &SamplerTest::debugCompareFunction, + #endif #ifndef MAGNUM_TARGET_GLES &SamplerTest::debugDepthStencilMode #endif @@ -58,44 +62,46 @@ SamplerTest::SamplerTest() { void SamplerTest::debugFilter() { std::ostringstream out; - Debug(&out) << Sampler::Filter::Linear; - CORRADE_COMPARE(out.str(), "Sampler::Filter::Linear\n"); + Debug(&out) << Sampler::Filter::Linear << Sampler::Filter(0xdead); + CORRADE_COMPARE(out.str(), "Sampler::Filter::Linear Sampler::Filter(0xdead)\n"); } void SamplerTest::debugMipmap() { std::ostringstream out; - Debug(&out) << Sampler::Mipmap::Base; - CORRADE_COMPARE(out.str(), "Sampler::Mipmap::Base\n"); + Debug(&out) << Sampler::Mipmap::Base << Sampler::Mipmap(0xdead); + CORRADE_COMPARE(out.str(), "Sampler::Mipmap::Base Sampler::Mipmap(0xdead)\n"); } void SamplerTest::debugWrapping() { std::ostringstream out; - Debug(&out) << Sampler::Wrapping::ClampToEdge; - CORRADE_COMPARE(out.str(), "Sampler::Wrapping::ClampToEdge\n"); + Debug(&out) << Sampler::Wrapping::ClampToEdge << Sampler::Wrapping(0xdead); + CORRADE_COMPARE(out.str(), "Sampler::Wrapping::ClampToEdge Sampler::Wrapping(0xdead)\n"); } +#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void SamplerTest::debugCompareMode() { std::ostringstream out; - Debug(&out) << Sampler::CompareMode::CompareRefToTexture; - CORRADE_COMPARE(out.str(), "Sampler::CompareMode::CompareRefToTexture\n"); + Debug(&out) << Sampler::CompareMode::CompareRefToTexture << Sampler::CompareMode(0xdead); + CORRADE_COMPARE(out.str(), "Sampler::CompareMode::CompareRefToTexture Sampler::CompareMode(0xdead)\n"); } void SamplerTest::debugCompareFunction() { std::ostringstream out; - Debug(&out) << Sampler::CompareFunction::GreaterOrEqual; - CORRADE_COMPARE(out.str(), "Sampler::CompareFunction::GreaterOrEqual\n"); + Debug(&out) << Sampler::CompareFunction::GreaterOrEqual << Sampler::CompareFunction(0xdead); + CORRADE_COMPARE(out.str(), "Sampler::CompareFunction::GreaterOrEqual Sampler::CompareFunction(0xdead)\n"); } +#endif #ifndef MAGNUM_TARGET_GLES void SamplerTest::debugDepthStencilMode() { std::ostringstream out; - Debug(&out) << Sampler::DepthStencilMode::StencilIndex; - CORRADE_COMPARE(out.str(), "Sampler::DepthStencilMode::StencilIndex\n"); + Debug(&out) << Sampler::DepthStencilMode::StencilIndex << Sampler::DepthStencilMode(0xdead); + CORRADE_COMPARE(out.str(), "Sampler::DepthStencilMode::StencilIndex Sampler::DepthStencilMode(0xdead)\n"); } #endif diff --git a/src/Magnum/Test/ShaderGLTest.cpp b/src/Magnum/Test/ShaderGLTest.cpp index be28f5345..519bf35a1 100644 --- a/src/Magnum/Test/ShaderGLTest.cpp +++ b/src/Magnum/Test/ShaderGLTest.cpp @@ -45,8 +45,10 @@ struct ShaderGLTest: AbstractOpenGLTester { void label(); void addSource(); + void addSourceNoVersion(); void addFile(); void compile(); + void compileNoVersion(); }; ShaderGLTest::ShaderGLTest() { @@ -58,8 +60,10 @@ ShaderGLTest::ShaderGLTest() { &ShaderGLTest::label, &ShaderGLTest::addSource, + &ShaderGLTest::addSourceNoVersion, &ShaderGLTest::addFile, - &ShaderGLTest::compile}); + &ShaderGLTest::compile, + &ShaderGLTest::compileNoVersion}); } void ShaderGLTest::construct() { @@ -183,6 +187,38 @@ void ShaderGLTest::addSource() { #endif } +void ShaderGLTest::addSourceNoVersion() { + Shader shader(Version::None, Shader::Type::Fragment); + + #ifndef MAGNUM_TARGET_GLES + shader.addSource("#version 120\n"); + #else + shader.addSource("#version 100\n"); + #endif + shader.addSource("#define FOO BAR\n") + .addSource("void main() {}\n"); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(shader.sources(), (std::vector{ + "", + "#version 120\n", + "#line 1 1\n", + "#define FOO BAR\n", + "#line 1 2\n", + "void main() {}\n" + })); + #else + CORRADE_COMPARE(shader.sources(), (std::vector{ + "", + "#version 100\n", + "#line 1 1\n", + "#define FOO BAR\n", + "#line 1 2\n", + "void main() {}\n" + })); + #endif +} + void ShaderGLTest::addFile() { #ifndef MAGNUM_TARGET_GLES Shader shader(Version::GL210, Shader::Type::Fragment); @@ -229,6 +265,16 @@ void ShaderGLTest::compile() { CORRADE_VERIFY(!shader2.compile()); } +void ShaderGLTest::compileNoVersion() { + Shader shader(Version::None, Shader::Type::Fragment); + #ifndef MAGNUM_TARGET_GLES + shader.addSource("#version 120\nvoid main() {}\n"); + #else + shader.addSource("#version 100\nvoid main() {}\n"); + #endif + CORRADE_VERIFY(shader.compile()); +} + }} MAGNUM_GL_TEST_MAIN(Magnum::Test::ShaderGLTest) diff --git a/src/Magnum/Test/ShaderTest.cpp b/src/Magnum/Test/ShaderTest.cpp index 6a1f928e1..aaa24a0cf 100644 --- a/src/Magnum/Test/ShaderTest.cpp +++ b/src/Magnum/Test/ShaderTest.cpp @@ -43,8 +43,8 @@ ShaderTest::ShaderTest() { void ShaderTest::debugType() { std::ostringstream out; - Debug(&out) << Shader::Type::Fragment; - CORRADE_COMPARE(out.str(), "Shader::Type::Fragment\n"); + Debug(&out) << Shader::Type::Fragment << Shader::Type(0xdead); + CORRADE_COMPARE(out.str(), "Shader::Type::Fragment Shader::Type(0xdead)\n"); } }} diff --git a/src/Magnum/Test/TimeQueryGLTest.cpp b/src/Magnum/Test/TimeQueryGLTest.cpp index 4860ccc16..292c50acc 100644 --- a/src/Magnum/Test/TimeQueryGLTest.cpp +++ b/src/Magnum/Test/TimeQueryGLTest.cpp @@ -23,6 +23,8 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/TimeQuery.h" #include "Magnum/Test/AbstractOpenGLTester.h" @@ -112,7 +114,7 @@ void TimeQueryGLTest::queryTime() { const auto result2 = q2.result(); MAGNUM_VERIFY_NO_ERROR(); - CORRADE_VERIFY(result2 >= result1); + CORRADE_COMPARE_AS(result2, result1, TestSuite::Compare::GreaterOrEqual); } void TimeQueryGLTest::queryTimestamp() { @@ -139,8 +141,8 @@ void TimeQueryGLTest::queryTimestamp() { const auto result2 = q2.result(); MAGNUM_VERIFY_NO_ERROR(); - CORRADE_VERIFY(result2 >= result1); - CORRADE_VERIFY(result2-result1 >= result); + CORRADE_COMPARE_AS(result2, result1, TestSuite::Compare::GreaterOrEqual); + CORRADE_COMPARE_AS(result2 - result1, result, TestSuite::Compare::GreaterOrEqual); } }} diff --git a/src/Magnum/Test/TransformFeedbackGLTest.cpp b/src/Magnum/Test/TransformFeedbackGLTest.cpp index 396ef680e..f122c4c57 100644 --- a/src/Magnum/Test/TransformFeedbackGLTest.cpp +++ b/src/Magnum/Test/TransformFeedbackGLTest.cpp @@ -26,7 +26,11 @@ #include "Magnum/AbstractShaderProgram.h" #include "Magnum/Buffer.h" #include "Magnum/Framebuffer.h" +#include "Magnum/Image.h" #include "Magnum/Mesh.h" +#include "Magnum/PixelFormat.h" +#include "Magnum/PrimitiveQuery.h" +#include "Magnum/SampleQuery.h" #include "Magnum/Renderbuffer.h" #include "Magnum/RenderbufferFormat.h" #include "Magnum/Shader.h" @@ -54,9 +58,31 @@ struct TransformFeedbackGLTest: AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES void interleaved(); + + void draw(); #endif }; +namespace { + +enum: std::size_t { DrawDataCount = 4 }; + +const struct { + const char* name; + UnsignedInt stream; + Int instances; + UnsignedInt countStream0; + UnsignedInt countStreamN; + UnsignedInt countDraw; +} DrawData[DrawDataCount] = { + {"basic", 0, 1, 6, 6, 6}, + {"instanced", 0, 5, 6, 6, 30}, + {"stream", 1, 1, 0, 6, 6}, + {"streamInstanced", 1, 5, 0, 6, 30} +}; + +} + TransformFeedbackGLTest::TransformFeedbackGLTest() { addTests({&TransformFeedbackGLTest::construct, &TransformFeedbackGLTest::constructNoCreate, @@ -72,9 +98,13 @@ TransformFeedbackGLTest::TransformFeedbackGLTest() { &TransformFeedbackGLTest::attachRanges, #ifndef MAGNUM_TARGET_GLES - &TransformFeedbackGLTest::interleaved + &TransformFeedbackGLTest::interleaved, #endif }); + + #ifndef MAGNUM_TARGET_GLES + addInstancedTests({&TransformFeedbackGLTest::draw}, DrawDataCount); + #endif } void TransformFeedbackGLTest::construct() { @@ -530,6 +560,140 @@ void TransformFeedbackGLTest::interleaved() { CORRADE_COMPARE(data[3].y(), 3.0f); output.unmap(); } + +void TransformFeedbackGLTest::draw() { + /* ARB_transform_feedback2 needed as base, other optional */ + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::transform_feedback2::string() + std::string(" is not supported.")); + if(DrawData[testCaseInstanceId()].stream && !Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::transform_feedback3::string() + std::string(" is not supported.")); + if(DrawData[testCaseInstanceId()].instances && !Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::transform_feedback_instanced::string() + std::string(" is not supported.")); + + setTestCaseDescription(DrawData[testCaseInstanceId()].name); + + /* Bind some FB to avoid errors on contexts w/o default FB */ + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, Vector2i{1}); + Framebuffer fb{{{}, Vector2i{1}}}; + fb.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color) + .bind(); + + struct XfbShader: AbstractShaderProgram { + explicit XfbShader(UnsignedInt stream) { + Shader vert{stream ? Version::GL400 : Version::GL320, Shader::Type::Vertex}, + geom{stream ? Version::GL400 : Version::GL320, Shader::Type::Geometry}; + vert.addSource( + "out mediump vec2 vertexOutput;\n" + "void main() {\n" + " vertexOutput = vec2(0.3);\n" + " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" + "}\n"); + if(stream) geom.addSource( + "#define STREAM " + std::to_string(stream) + "\n" + + "layout(stream = 0) out mediump float otherOutput;\n" + + "layout(stream = STREAM) out mediump vec2 geomOutput;\n"); + else geom.addSource( + "out mediump vec2 geomOutput;\n"); + geom.addSource( + "layout(points) in;\n" + "layout(points, max_vertices = 1) out;\n" + "in mediump vec2 vertexOutput[];\n" + "void main() {\n" + " geomOutput = vertexOutput[0] - vec2(0.1);\n"); + if(stream) geom.addSource( + " EmitStreamVertex(STREAM);\n"); + else geom.addSource( + " EmitVertex();\n"); + geom.addSource("}\n"); + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, geom})); + attachShaders({vert, geom}); + setTransformFeedbackOutputs({"geomOutput"}, TransformFeedbackBufferMode::SeparateAttributes); + CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + } + } xfbShader{DrawData[testCaseInstanceId()].stream}; + + Buffer outputBuffer; + outputBuffer.setData({nullptr, 32*sizeof(Vector2)}, BufferUsage::StaticDraw); + + Mesh inputMesh; + inputMesh.setPrimitive(MeshPrimitive::Points) + .setCount(6); + + TransformFeedback feedback; + feedback.attachBuffer(0, outputBuffer); + + MAGNUM_VERIFY_NO_ERROR(); + + PrimitiveQuery queryStream0{PrimitiveQuery::Target::TransformFeedbackPrimitivesWritten}, + queryStreamN{PrimitiveQuery::Target::TransformFeedbackPrimitivesWritten}; + + queryStream0.begin(); + if(DrawData[testCaseInstanceId()].stream) + queryStreamN.begin(DrawData[testCaseInstanceId()].stream); + + Renderer::enable(Renderer::Feature::RasterizerDiscard); + feedback.begin(xfbShader, TransformFeedback::PrimitiveMode::Points); + inputMesh.draw(xfbShader); + feedback.end(); + Renderer::disable(Renderer::Feature::RasterizerDiscard); + + if(DrawData[testCaseInstanceId()].stream) + queryStreamN.end(); + queryStream0.end(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(queryStream0.result(), DrawData[testCaseInstanceId()].countStream0); + if(DrawData[testCaseInstanceId()].stream) + CORRADE_COMPARE(queryStreamN.result(), DrawData[testCaseInstanceId()].countStreamN); + + struct DrawShader: AbstractShaderProgram { + typedef Attribute<0, Vector2> Input; + + explicit DrawShader() { + Shader vert{Version::GL320, Shader::Type::Vertex}, + frag{Version::GL320, Shader::Type::Fragment}; + vert.addSource( + "in mediump vec2 inputData;\n" + "out mediump vec2 interleaved;\n" + "void main() {\n" + " interleaved = inputData;\n" + " gl_Position = vec4(1.0);\n" + "}\n"); + frag.addSource( + "in mediump vec2 interleaved;\n" + "out mediump float outputData;\n" + "void main() {\n" + " outputData = interleaved.x + 2*interleaved.y;\n" + "}\n"); + + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); + attachShaders({vert, frag}); + bindAttributeLocation(Input::Location, "inputData"); + CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + } + } drawShader; + + Renderer::setPointSize(2.0f); + + Mesh outputMesh; + outputMesh.setPrimitive(MeshPrimitive::Points) + .setInstanceCount(DrawData[testCaseInstanceId()].instances) + .addVertexBuffer(outputBuffer, 0, DrawShader::Input{}); + + PrimitiveQuery q{PrimitiveQuery::Target::PrimitivesGenerated}; + q.begin(); + outputMesh.draw(drawShader, feedback, DrawData[testCaseInstanceId()].stream); + q.end(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(q.result(), DrawData[testCaseInstanceId()].countDraw); + CORRADE_COMPARE(fb.read({{}, Vector2i{1}}, {PixelFormat::RGBA, PixelType::UnsignedByte}).data()[0], 153); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif }} diff --git a/src/Magnum/Test/VersionTest.cpp b/src/Magnum/Test/VersionTest.cpp index d439b7b02..3ce871418 100644 --- a/src/Magnum/Test/VersionTest.cpp +++ b/src/Magnum/Test/VersionTest.cpp @@ -108,10 +108,12 @@ void VersionTest::debug() { Debug(&out) << Version::GLES200; #endif - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(out.str(), "OpenGL 2.1\n"); - #else + #ifdef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE(out.str(), "WebGL 1.0\n"); + #elif defined(MAGNUM_TARGET_GLES) CORRADE_COMPARE(out.str(), "OpenGL ES 2.0\n"); + #else + CORRADE_COMPARE(out.str(), "OpenGL 2.1\n"); #endif } diff --git a/src/Magnum/Text/AbstractFont.h b/src/Magnum/Text/AbstractFont.h index 3af3f3ddc..c8a90eb5c 100644 --- a/src/Magnum/Text/AbstractFont.h +++ b/src/Magnum/Text/AbstractFont.h @@ -362,7 +362,7 @@ class MAGNUM_TEXT_EXPORT AbstractLayouter { /** @brief Moving is not allowed */ AbstractLayouter(AbstractLayouter&&) = delete; - ~AbstractLayouter(); + virtual ~AbstractLayouter(); /** @brief Copying is not allowed */ AbstractLayouter& operator=(const AbstractLayouter&) = delete; diff --git a/src/Magnum/Text/AbstractFontConverter.h b/src/Magnum/Text/AbstractFontConverter.h index 22c4c264c..5d5c3810c 100644 --- a/src/Magnum/Text/AbstractFontConverter.h +++ b/src/Magnum/Text/AbstractFontConverter.h @@ -69,6 +69,11 @@ checked by the implementation: array passed. Plugin interface string is `"cz.mosra.magnum.Text.AbstractFontConverter/0.1.2"`. + +@attention @ref Corrade::Containers::Array instances returned from the plugin + should *not* use anything else than the default deleter, otherwise this can + cause dangling function pointer call on array destruction if the plugin + gets unloaded before the array is destroyed. */ class MAGNUM_TEXT_EXPORT AbstractFontConverter: public PluginManager::AbstractPlugin { CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFontConverter/0.1.2") diff --git a/src/Magnum/Text/CMakeLists.txt b/src/Magnum/Text/CMakeLists.txt index 0f97736d9..5190538b4 100644 --- a/src/Magnum/Text/CMakeLists.txt +++ b/src/Magnum/Text/CMakeLists.txt @@ -65,12 +65,24 @@ if(WITH_FONTCONVERTER) target_link_libraries(magnum-fontconverter Magnum MagnumText) if(MAGNUM_TARGET_HEADLESS) target_link_libraries(magnum-fontconverter MagnumWindowlessEglApplication) + elseif(CORRADE_TARGET_IOS) + target_link_libraries(magnum-fontconverter MagnumWindowlessIosApplication) elseif(CORRADE_TARGET_APPLE) target_link_libraries(magnum-fontconverter MagnumWindowlessCglApplication) - elseif(CORRADE_TARGET_UNIX AND NOT TARGET_GLES) - target_link_libraries(magnum-fontconverter MagnumWindowlessGlxApplication) - elseif(CORRADE_TARGET_WINDOWS AND NOT TARGET_GLES) - target_link_libraries(magnum-fontconverter MagnumWindowlessWglApplication) + elseif(CORRADE_TARGET_NACL) + target_link_libraries(magnum-fontconverter MagnumWindowlessNaClApplication) + elseif(CORRADE_TARGET_UNIX) + if(MAGNUM_TARGET_GLES AND NOT MAGNUM_TARGET_DESKTOP_GLES) + target_link_libraries(magnum-fontconverter MagnumWindowlessEglApplication) + else() + target_link_libraries(magnum-fontconverter MagnumWindowlessGlxApplication) + endif() + elseif(CORRADE_TARGET_WINDOWS) + if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) + target_link_libraries(magnum-fontconverter MagnumWindowlessWglApplication) + else() + target_link_libraries(magnum-fontconverter MagnumWindowlessWindowsEglApplication) + endif() else() message(FATAL_ERROR "magnum-fontconverter is not available on this platform. Set WITH_FONTCONVERTER to OFF to suppress this warning.") endif() diff --git a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp index 3cca1727e..28773364c 100644 --- a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp @@ -62,6 +62,9 @@ AbstractFontConverterTest::AbstractFontConverterTest() { &AbstractFontConverterTest::importGlyphCacheFromSingleData, &AbstractFontConverterTest::importGlyphCacheFromFile}); + + /* Create testing dir */ + Utility::Directory::mkpath(TEXT_TEST_OUTPUT_DIR); } namespace { diff --git a/src/Magnum/Text/Test/CMakeLists.txt b/src/Magnum/Text/Test/CMakeLists.txt index 1fe654601..2693e77ed 100644 --- a/src/Magnum/Text/Test/CMakeLists.txt +++ b/src/Magnum/Text/Test/CMakeLists.txt @@ -23,12 +23,24 @@ # DEALINGS IN THE SOFTWARE. # +if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) + set(TEXT_TEST_DIR ".") + set(TEXT_TEST_OUTPUT_DIR "./write") +else() + set(TEXT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + set(TEXT_TEST_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure.h) -corrade_add_test(TextAbstractFontTest AbstractFontTest.cpp LIBRARIES Magnum MagnumText) +corrade_add_test(TextAbstractFontTest AbstractFontTest.cpp + LIBRARIES Magnum MagnumText + FILES data.bin) target_include_directories(TextAbstractFontTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -corrade_add_test(TextAbstractFontConverterTest AbstractFontConverterTest.cpp LIBRARIES Magnum MagnumText) +corrade_add_test(TextAbstractFontConverterTest AbstractFontConverterTest.cpp + LIBRARIES Magnum MagnumText + FILES data.bin) target_include_directories(TextAbstractFontConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) corrade_add_test(TextAbstractLayouterTest AbstractLayouterTest.cpp LIBRARIES Magnum MagnumText) diff --git a/src/Magnum/Text/Test/configure.h.cmake b/src/Magnum/Text/Test/configure.h.cmake index 96f3e6a59..e3f4cc05d 100644 --- a/src/Magnum/Text/Test/configure.h.cmake +++ b/src/Magnum/Text/Test/configure.h.cmake @@ -23,5 +23,5 @@ DEALINGS IN THE SOFTWARE. */ -#define TEXT_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" -#define TEXT_TEST_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}" +#define TEXT_TEST_DIR "${TEXT_TEST_DIR}" +#define TEXT_TEST_OUTPUT_DIR "${TEXT_TEST_OUTPUT_DIR}" diff --git a/src/Magnum/Text/fontconverter.cpp b/src/Magnum/Text/fontconverter.cpp index 78a90dbf4..5482b47f5 100644 --- a/src/Magnum/Text/fontconverter.cpp +++ b/src/Magnum/Text/fontconverter.cpp @@ -34,13 +34,25 @@ #ifdef MAGNUM_TARGET_HEADLESS #include "Magnum/Platform/WindowlessEglApplication.h" +#elif defined(CORRADE_TARGET_NACL) +#include "Magnum/Platform/WindowlessNaClApplication.h" +#elif defined(CORRADE_TARGET_IOS) +#include "Magnum/Platform/WindowlessIosApplication.h" #elif defined(CORRADE_TARGET_APPLE) #include "Magnum/Platform/WindowlessCglApplication.h" #elif defined(CORRADE_TARGET_UNIX) +#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_DESKTOP_GLES) +#include "Magnum/Platform/WindowlessEglApplication.h" +#else #include "Magnum/Platform/WindowlessGlxApplication.h" +#endif #elif defined(CORRADE_TARGET_WINDOWS) +#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_DESKTOP_GLES) #include "Magnum/Platform/WindowlessWglApplication.h" #else +#include "Magnum/Platform/WindowlessWindowsEglApplication.h" +#endif +#else #error no windowless application available on this platform #endif @@ -54,7 +66,7 @@ namespace Magnum { @section magnum-fontconverter-usage Usage - magnum-fontconverter [-h|--help] --font FONT --converter CONVERTER [--plugin-dir DIR] [--characters CHARACTERS] [--font-size N] [--atlas-size "X Y"] [--output-size "X Y"] [--radius N] [--] input output + magnum-fontconverter [--magnum-...] [-h|--help] --font FONT --converter CONVERTER [--plugin-dir DIR] [--characters CHARACTERS] [--font-size N] [--atlas-size "X Y"] [--output-size "X Y"] [--radius N] [--] input output Arguments: @@ -72,6 +84,7 @@ Arguments: - `--output-size "X Y"` -- output atlas size. If set to zero size, distance field computation will not be used. (default: `"256 256"`) - `--radius N` -- distance field computation radius (default: `24`) +- `--magnum-...` -- engine-specific options (see @ref Context for details) The resulting font files can be then used as specified in the documentation of `converter` plugin. @@ -101,12 +114,12 @@ class FontConverter: public Platform::WindowlessApplication { Utility::Arguments args; }; -FontConverter::FontConverter(const Arguments& arguments): Platform::WindowlessApplication(arguments, nullptr) { +FontConverter::FontConverter(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { args.addArgument("input").setHelp("input", "input font") .addArgument("output").setHelp("output", "output filename prefix") .addNamedArgument("font").setHelp("font", "font plugin") .addNamedArgument("converter").setHelp("converter", "font converter plugin") - .addOption("plugin-dir", MAGNUM_PLUGINS_DIR).setHelp("plugin-dir", "base plugin dir", "DIR") + .addOption("plugin-dir", Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), MAGNUM_PLUGINS_DIR)).setHelp("plugin-dir", "base plugin dir", "DIR") .addOption("characters", "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789?!:;,. ").setHelp("characters", "characters to include in the output") diff --git a/src/Magnum/Text/fontconverterConfigure.h.cmake b/src/Magnum/Text/fontconverterConfigure.h.cmake index 895e33c28..7411d07a9 100644 --- a/src/Magnum/Text/fontconverterConfigure.h.cmake +++ b/src/Magnum/Text/fontconverterConfigure.h.cmake @@ -24,7 +24,7 @@ */ #ifdef CORRADE_IS_DEBUG_BUILD -#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}" +#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DEBUG_DIR}" #else -#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_INSTALL_DIR}" +#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DIR}" #endif diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index d33498c42..60fceade3 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -1014,9 +1014,9 @@ template class Texture: public AbstractTexture { * and has better performance characteristics. This call also has no * equivalent in @extension{ARB,direct_state_access}, thus the texture * needs to be bound to some texture unit before the operation. - * @see @ref maxSize(), @fn_gl{PixelStore}, then @fn_gl{ActiveTexture}, - * @fn_gl{BindTexture} and @fn_gl{TexImage1D} / @fn_gl{TexImage2D} - * / @fn_gl{TexImage3D} + * @see @ref maxSize(), @ref Framebuffer::copyImage(), @fn_gl{PixelStore}, + * then @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexImage1D} + * / @fn_gl{TexImage2D} / @fn_gl{TexImage3D} * @deprecated_gl Prefer to use @ref setStorage() and @ref setSubImage() * instead. */ @@ -1115,7 +1115,8 @@ template class Texture: public AbstractTexture { * nor @extension{EXT,direct_state_access} desktop extension is * available, the texture is bound before the operation (if not * already). - * @see @ref setStorage(), @fn_gl{PixelStore}, @fn_gl2{TextureSubImage1D,TexSubImage1D} / + * @see @ref setStorage(), @ref Framebuffer::copySubImage(), + * @fn_gl{PixelStore}, @fn_gl2{TextureSubImage1D,TexSubImage1D} / * @fn_gl2{TextureSubImage2D,TexSubImage2D} / @fn_gl2{TextureSubImage3D,TexSubImage3D}, * @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access} / * @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access} / diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 5e9d364a6..c9c25a5f4 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -472,7 +472,6 @@ template class TextureArray: public AbstractTexture { #ifndef MAGNUM_TARGET_GLES /** * @copybrief Texture::image(Int, Image&) - * @return Reference to self (for method chaining) * * See @ref Texture::image(Int, Image&) for more information. * @requires_gl Texture image queries are not available in OpenGL ES or @@ -493,7 +492,6 @@ template class TextureArray: public AbstractTexture { /** * @copybrief Texture::image(Int, BufferImage&, BufferUsage) - * @return Reference to self (for method chaining) * * See @ref Texture::image(Int, BufferImage&, BufferUsage) for more * information. @@ -515,7 +513,6 @@ template class TextureArray: public AbstractTexture { /** * @copybrief Texture::compressedImage(Int, CompressedImage&) - * @return Reference to self (for method chaining) * * See @ref Texture::compressedImage(Int, CompressedImage&) for more * information. @@ -537,7 +534,6 @@ template class TextureArray: public AbstractTexture { /** * @copybrief Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) - * @return Reference to self (for method chaining) * * See @ref Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) * for more information. @@ -794,7 +790,6 @@ template class TextureArray: public AbstractTexture { /** * @copybrief Texture::invalidateImage() - * @return Reference to self (for method chaining) * * See @ref Texture::invalidateImage() for more information. */ @@ -802,7 +797,6 @@ template class TextureArray: public AbstractTexture { /** * @copybrief Texture::invalidateSubImage() - * @return Reference to self (for method chaining) * * See @ref Texture::invalidateSubImage() for more information. */ diff --git a/src/Magnum/TextureTools/CMakeLists.txt b/src/Magnum/TextureTools/CMakeLists.txt index e93c999c6..883ed4c87 100644 --- a/src/Magnum/TextureTools/CMakeLists.txt +++ b/src/Magnum/TextureTools/CMakeLists.txt @@ -55,12 +55,24 @@ if(WITH_DISTANCEFIELDCONVERTER) target_link_libraries(magnum-distancefieldconverter Magnum MagnumTextureTools) if(MAGNUM_TARGET_HEADLESS) target_link_libraries(magnum-distancefieldconverter MagnumWindowlessEglApplication) + elseif(CORRADE_TARGET_IOS) + target_link_libraries(magnum-distancefieldconverter MagnumWindowlessIosApplication) elseif(CORRADE_TARGET_APPLE) target_link_libraries(magnum-distancefieldconverter MagnumWindowlessCglApplication) - elseif(CORRADE_TARGET_UNIX AND NOT TARGET_GLES) - target_link_libraries(magnum-distancefieldconverter MagnumWindowlessGlxApplication) - elseif(CORRADE_TARGET_WINDOWS AND NOT TARGET_GLES) - target_link_libraries(magnum-distancefieldconverter MagnumWindowlessWglApplication) + elseif(CORRADE_TARGET_NACL) + target_link_libraries(magnum-distancefieldconverter MagnumWindowlessNaClApplication) + elseif(CORRADE_TARGET_UNIX) + if(MAGNUM_TARGET_GLES AND NOT MAGNUM_TARGET_DESKTOP_GLES) + target_link_libraries(magnum-distancefieldconverter MagnumWindowlessEglApplication) + else() + target_link_libraries(magnum-distancefieldconverter MagnumWindowlessGlxApplication) + endif() + elseif(CORRADE_TARGET_WINDOWS) + if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) + target_link_libraries(magnum-distancefieldconverter MagnumWindowlessWglApplication) + else() + target_link_libraries(magnum-distancefieldconverter MagnumWindowlessWindowsEglApplication) + endif() else() message(FATAL_ERROR "magnum-distancefieldconverter is not available on this platform. Set WITH_DISTANCEFIELDCONVERTER to OFF to suppress this warning.") endif() diff --git a/src/Magnum/TextureTools/distancefieldconverter.cpp b/src/Magnum/TextureTools/distancefieldconverter.cpp index bded817b8..45a042aa1 100644 --- a/src/Magnum/TextureTools/distancefieldconverter.cpp +++ b/src/Magnum/TextureTools/distancefieldconverter.cpp @@ -40,13 +40,25 @@ #ifdef MAGNUM_TARGET_HEADLESS #include "Magnum/Platform/WindowlessEglApplication.h" +#elif defined(CORRADE_TARGET_NACL) +#include "Magnum/Platform/WindowlessNaClApplication.h" +#elif defined(CORRADE_TARGET_IOS) +#include "Magnum/Platform/WindowlessIosApplication.h" #elif defined(CORRADE_TARGET_APPLE) #include "Magnum/Platform/WindowlessCglApplication.h" #elif defined(CORRADE_TARGET_UNIX) +#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_DESKTOP_GLES) +#include "Magnum/Platform/WindowlessEglApplication.h" +#else #include "Magnum/Platform/WindowlessGlxApplication.h" +#endif #elif defined(CORRADE_TARGET_WINDOWS) +#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_DESKTOP_GLES) #include "Magnum/Platform/WindowlessWglApplication.h" #else +#include "Magnum/Platform/WindowlessWindowsEglApplication.h" +#endif +#else #error no windowless application available on this platform #endif @@ -59,7 +71,7 @@ namespace Magnum { @section magnum-distancefieldconverter-usage Usage - magnum-distancefieldconverter [-h|--help] [--importer IMPORTER] [--converter CONVERTER] [--plugin-dir DIR] --output-size "X Y" --radius N [--] input output + magnum-distancefieldconverter [--magnum-...] [-h|--help] [--importer IMPORTER] [--converter CONVERTER] [--plugin-dir DIR] --output-size "X Y" --radius N [--] input output Arguments: @@ -72,6 +84,7 @@ Arguments: Magnum install location) - `--output-size "X Y"` -- size of output image - `--radius N` -- distance field computation radius +- `--magnum-...` -- engine-specific options (see @ref Context for details) Images with @ref PixelFormat::Red, @ref PixelFormat::RGB or @ref PixelFormat::RGBA are accepted on input. @@ -102,12 +115,12 @@ class DistanceFieldConverter: public Platform::WindowlessApplication { Utility::Arguments args; }; -DistanceFieldConverter::DistanceFieldConverter(const Arguments& arguments): Platform::WindowlessApplication(arguments, nullptr) { +DistanceFieldConverter::DistanceFieldConverter(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { args.addArgument("input").setHelp("input", "input image") .addArgument("output").setHelp("output", "output image") .addOption("importer", "AnyImageImporter").setHelp("importer", "image importer plugin") .addOption("converter", "AnyImageConverter").setHelp("converter", "image converter plugin") - .addOption("plugin-dir", MAGNUM_PLUGINS_DIR).setHelp("plugin-dir", "base plugin dir", "DIR") + .addOption("plugin-dir", Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), MAGNUM_PLUGINS_DIR)).setHelp("plugin-dir", "base plugin dir", "DIR") .addNamedArgument("output-size").setHelp("output-size", "size of output image", "\"X Y\"") .addNamedArgument("radius").setHelp("radius", "distance field computation radius", "N") .addSkippedPrefix("magnum", "engine-specific options") diff --git a/src/Magnum/TextureTools/distancefieldconverterConfigure.h.cmake b/src/Magnum/TextureTools/distancefieldconverterConfigure.h.cmake index 895e33c28..7411d07a9 100644 --- a/src/Magnum/TextureTools/distancefieldconverterConfigure.h.cmake +++ b/src/Magnum/TextureTools/distancefieldconverterConfigure.h.cmake @@ -24,7 +24,7 @@ */ #ifdef CORRADE_IS_DEBUG_BUILD -#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}" +#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DEBUG_DIR}" #else -#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_INSTALL_DIR}" +#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DIR}" #endif diff --git a/src/Magnum/TimeQuery.h b/src/Magnum/TimeQuery.h index 4d5b7e068..23c1649d2 100644 --- a/src/Magnum/TimeQuery.h +++ b/src/Magnum/TimeQuery.h @@ -81,14 +81,22 @@ class TimeQuery: public AbstractQuery { public: /** @brief Query target */ enum class Target: GLenum { - /** Elapsed time */ + /** + * Elapsed time. Use @ref result() or @ref result() + * to retrieve the result. + * @see @ref timestamp() + */ #ifndef MAGNUM_TARGET_GLES TimeElapsed = GL_TIME_ELAPSED, #else TimeElapsed = GL_TIME_ELAPSED_EXT, #endif - /** Timestamp (for use with @ref timestamp() only) */ + /** + * Timestamp. For use with @ref timestamp() only, use + * @ref result() or @ref result() to retrieve + * the result. + */ #ifndef MAGNUM_TARGET_GLES Timestamp = GL_TIMESTAMP #else @@ -141,9 +149,23 @@ class TimeQuery: public AbstractQuery { */ explicit TimeQuery(NoCreateT) noexcept: AbstractQuery{NoCreate, GLenum(Target::TimeElapsed)} {} + /* Overloads to remove WTF-factor from method chaining order */ + #if !defined(DOXYGEN_GENERATING_OUTPUT) && !defined(MAGNUM_TARGET_WEBGL) + TimeQuery& setLabel(const std::string& label) { + AbstractQuery::setLabel(label); + return *this; + } + template TimeQuery& setLabel(const char(&label)[size]) { + AbstractQuery::setLabel(label); + return *this; + } + #endif + /** * @brief Query timestamp * + * Use @ref result() or @ref result() to retrieve + * the result. * @see @fn_gl{QueryCounter} with @def_gl{TIMESTAMP} */ void timestamp() { @@ -152,7 +174,7 @@ class TimeQuery: public AbstractQuery { #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) glQueryCounterEXT(id(), GL_TIMESTAMP_EXT); #else - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ #endif } @@ -168,18 +190,6 @@ class TimeQuery: public AbstractQuery { using AbstractQuery::begin; #endif - /* Overloads to remove WTF-factor from method chaining order */ - #if !defined(DOXYGEN_GENERATING_OUTPUT) && !defined(MAGNUM_TARGET_WEBGL) - TimeQuery& setLabel(const std::string& label) { - AbstractQuery::setLabel(label); - return *this; - } - template TimeQuery& setLabel(const char(&label)[size]) { - AbstractQuery::setLabel(label); - return *this; - } - #endif - private: explicit TimeQuery(GLuint id, Target target, ObjectFlags flags) noexcept: AbstractQuery{id, GLenum(target), flags} {} }; diff --git a/src/Magnum/Timeline.cpp b/src/Magnum/Timeline.cpp index a05790bc5..b38574209 100644 --- a/src/Magnum/Timeline.cpp +++ b/src/Magnum/Timeline.cpp @@ -26,7 +26,7 @@ #include "Timeline.h" #include -#include +#include #include "Magnum/Magnum.h" @@ -57,7 +57,7 @@ void Timeline::nextFrame() { #ifdef MAGNUM_BUILD_DEPRECATED if(_previousFrameDuration < _minimalFrameTime) { - Utility::sleep(std::size_t(_minimalFrameTime*1000) - duration/1000); + Utility::System::sleep(std::size_t(_minimalFrameTime*1000) - duration/1000); now = high_resolution_clock::now(); _previousFrameDuration = duration_cast(now-_previousFrameTime).count()/1e6f; } diff --git a/src/Magnum/Trade/AbstractImageConverter.cpp b/src/Magnum/Trade/AbstractImageConverter.cpp index d3589bf7d..1bbb92cc0 100644 --- a/src/Magnum/Trade/AbstractImageConverter.cpp +++ b/src/Magnum/Trade/AbstractImageConverter.cpp @@ -30,6 +30,7 @@ #include #include "Magnum/Image.h" +#include "Magnum/Trade/ImageData.h" namespace Magnum { namespace Trade { @@ -87,6 +88,10 @@ Containers::Array AbstractImageConverter::doExportToData(const CompressedI return nullptr; } +Containers::Array AbstractImageConverter::exportToData(const ImageData2D& image) { + return image.isCompressed() ? exportToData(CompressedImageView2D(image)) : exportToData(ImageView2D(image)); +} + bool AbstractImageConverter::exportToFile(const ImageView2D& image, const std::string& filename) { CORRADE_ASSERT(features() & Feature::ConvertFile, "Trade::AbstractImageConverter::exportToFile(): feature not supported", {}); @@ -131,4 +136,8 @@ bool AbstractImageConverter::doExportToFile(const CompressedImageView2D& image, return true; } +bool AbstractImageConverter::exportToFile(const ImageData2D& image, const std::string& filename) { + return image.isCompressed() ? exportToFile(CompressedImageView2D(image), filename) : exportToFile(ImageView2D(image), filename); +} + }} diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index b5215f60d..facb2eaad 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -33,6 +33,7 @@ #include "Magnum/Magnum.h" #include "Magnum/visibility.h" +#include "Magnum/Trade/Trade.h" #include "MagnumExternal/Optional/optional.hpp" namespace Magnum { namespace Trade { @@ -63,6 +64,11 @@ checked by the implementation: if @ref Feature::ConvertCompressedData is supported. Plugin interface string is `"cz.mosra.magnum.Trade.AbstractImageConverter/0.2.1"`. + +@attention @ref Corrade::Containers::Array instances returned from the plugin + should *not* use anything else than the default deleter, otherwise this can + cause dangling function pointer call on array destruction if the plugin + gets unloaded before the array is destroyed. */ class MAGNUM_EXPORT AbstractImageConverter: public PluginManager::AbstractManagingPlugin { CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Trade.AbstractImageConverter/0.2.1") @@ -157,6 +163,16 @@ class MAGNUM_EXPORT AbstractImageConverter: public PluginManager::AbstractManagi */ Containers::Array exportToData(const CompressedImageView2D& image); + /** + * @brief Export image to raw data + * + * Based on whether the image is compressed or not, calls either + * @ref exportToData(const ImageView2D&) or + * @ref exportToData(const CompressedImageView2D&). See documentation + * of those two functions for details. + */ + Containers::Array exportToData(const ImageData2D& image); + /** * @brief Export image to file * @@ -179,6 +195,16 @@ class MAGNUM_EXPORT AbstractImageConverter: public PluginManager::AbstractManagi */ bool exportToFile(const CompressedImageView2D& image, const std::string& filename); + /** + * @brief Export image to file + * + * Based on whether the image is compressed or not, calls either + * @ref exportToFile(const ImageView2D&, const std::string&) or + * @ref exportToFile(const CompressedImageView2D&, const std::string&). + * See documentation of those two functions for details. + */ + bool exportToFile(const ImageData2D& image, const std::string& filename); + #ifndef DOXYGEN_GENERATING_OUTPUT private: #else diff --git a/src/Magnum/Trade/AbstractImporter.h b/src/Magnum/Trade/AbstractImporter.h index f0bf089e3..780da4ce3 100644 --- a/src/Magnum/Trade/AbstractImporter.h +++ b/src/Magnum/Trade/AbstractImporter.h @@ -74,6 +74,11 @@ checked by the implementation: Plugin interface string is `"cz.mosra.magnum.Trade.AbstractImporter/0.3"`. +@attention @ref Corrade::Containers::Array instances returned from the plugin + should *not* use anything else than the default deleter, otherwise this can + cause dangling function pointer call on array destruction if the plugin + gets unloaded before the array is destroyed. + @todo How to handle casting from std::unique_ptr<> in more convenient way? */ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlugin { diff --git a/src/Magnum/Trade/AbstractMaterialData.cpp b/src/Magnum/Trade/AbstractMaterialData.cpp index c60d10001..9f9b33d9a 100644 --- a/src/Magnum/Trade/AbstractMaterialData.cpp +++ b/src/Magnum/Trade/AbstractMaterialData.cpp @@ -29,18 +29,20 @@ namespace Magnum { namespace Trade { -AbstractMaterialData::AbstractMaterialData(const MaterialType type, const void* const importerState): _type{type}, _importerState{importerState} {} +AbstractMaterialData::AbstractMaterialData(const MaterialType type, const void* const importerState) noexcept: _type{type}, _importerState{importerState} {} AbstractMaterialData::~AbstractMaterialData() {} Debug& operator<<(Debug& debug, const MaterialType value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case MaterialType::value: return debug << "Trade::MaterialType::" #value; _c(Phong) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Trade::MaterialType::(unknown)"; + return debug << "Trade::MaterialType(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } }} diff --git a/src/Magnum/Trade/AbstractMaterialData.h b/src/Magnum/Trade/AbstractMaterialData.h index 894d10ea2..47e89ce64 100644 --- a/src/Magnum/Trade/AbstractMaterialData.h +++ b/src/Magnum/Trade/AbstractMaterialData.h @@ -40,7 +40,7 @@ namespace Magnum { namespace Trade { @see @ref AbstractMaterialData::type() */ enum class MaterialType: UnsignedByte { - Phong /**< Phong shading */ + Phong /**< Phong shading (see @ref PhongMaterialData) */ }; /** @@ -50,27 +50,19 @@ Subclasses provide access to parameters for given material type. */ class MAGNUM_EXPORT AbstractMaterialData { public: - /** - * @brief Constructor - * @param type Material type - * @param importerState Importer-specific state - */ - explicit AbstractMaterialData(MaterialType type, const void* importerState = nullptr); - - /** @brief Destructor */ - virtual ~AbstractMaterialData() = 0; + virtual ~AbstractMaterialData(); /** @brief Copying is not allowed */ AbstractMaterialData(const AbstractMaterialData&) = delete; /** @brief Move constructor */ - AbstractMaterialData(AbstractMaterialData&&) = default; + AbstractMaterialData(AbstractMaterialData&&) noexcept = default; /** @brief Copying is not allowed */ AbstractMaterialData& operator=(const AbstractMaterialData&) = delete; /** @brief Move assignment */ - AbstractMaterialData& operator=(AbstractMaterialData&&) = default; + AbstractMaterialData& operator=(AbstractMaterialData&&) noexcept = default; /** @brief Material type */ MaterialType type() const { return _type; } @@ -82,6 +74,14 @@ class MAGNUM_EXPORT AbstractMaterialData { */ const void* importerState() const { return _importerState; } + protected: + /** + * @brief Constructor + * @param type Material type + * @param importerState Importer-specific state + */ + explicit AbstractMaterialData(MaterialType type, const void* importerState = nullptr) noexcept; + private: MaterialType _type; const void* _importerState; diff --git a/src/Magnum/Trade/CMakeLists.txt b/src/Magnum/Trade/CMakeLists.txt index 59f0b8d44..e3d997aa6 100644 --- a/src/Magnum/Trade/CMakeLists.txt +++ b/src/Magnum/Trade/CMakeLists.txt @@ -46,6 +46,20 @@ add_custom_target(MagnumTrade SOURCES ${MagnumTrade_HEADERS}) install(FILES ${MagnumTrade_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Trade) +if(WITH_IMAGECONVERTER) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/imageconverterConfigure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/imageconverterConfigure.h) + + add_executable(magnum-imageconverter imageconverter.cpp) + target_include_directories(magnum-imageconverter PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + target_link_libraries(magnum-imageconverter Magnum) + + install(TARGETS magnum-imageconverter DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}) + + # Magnum imageconverter target alias for superprojects + add_executable(Magnum::imageconverter ALIAS magnum-imageconverter) +endif() + if(BUILD_TESTS) add_subdirectory(Test) endif() diff --git a/src/Magnum/Trade/CameraData.h b/src/Magnum/Trade/CameraData.h index 7daa4acd2..1b7f2d7b8 100644 --- a/src/Magnum/Trade/CameraData.h +++ b/src/Magnum/Trade/CameraData.h @@ -54,6 +54,18 @@ class CameraData { */ explicit CameraData(Rad fov, Float near, Float far, const void* importerState = nullptr) noexcept; + /** @brief Copying is not allowed */ + CameraData(const CameraData&) = delete; + + /** @brief Move constructor */ + CameraData(CameraData&&) noexcept = default; + + /** @brief Copying is not allowed */ + CameraData& operator=(const CameraData&) = delete; + + /** @brief Move assignment */ + CameraData& operator=(CameraData&&) noexcept = default; + /** @brief Field-of-view angle */ Rad fov() const { return _fov; } diff --git a/src/Magnum/Trade/ImageData.cpp b/src/Magnum/Trade/ImageData.cpp index e4d1f3a87..f94b914f9 100644 --- a/src/Magnum/Trade/ImageData.cpp +++ b/src/Magnum/Trade/ImageData.cpp @@ -27,7 +27,7 @@ namespace Magnum { namespace Trade { -template ImageData::ImageData(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor& size, Containers::Array&& data, const void* const importerState): _compressed{false}, _storage{storage}, _format{format}, _type{type}, _size{size}, _data{std::move(data)}, _importerState{importerState} { +template ImageData::ImageData(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor& size, Containers::Array&& data, const void* const importerState) noexcept: _compressed{false}, _storage{storage}, _format{format}, _type{type}, _size{size}, _data{std::move(data)}, _importerState{importerState} { CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Trade::ImageData::ImageData(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); } @@ -63,7 +63,7 @@ template std::size_t ImageData::pixelSize() return PixelStorage::pixelSize(_format, _type); } -template std::tuple, std::size_t> ImageData::dataProperties() const { +template std::tuple, VectorTypeFor, std::size_t> ImageData::dataProperties() const { CORRADE_ASSERT(!_compressed, "Trade::ImageData::dataProperties(): the image is compressed", {}); return Implementation::imageDataProperties(*this); } diff --git a/src/Magnum/Trade/ImageData.h b/src/Magnum/Trade/ImageData.h index 7ff2e5561..33b1d3dd7 100644 --- a/src/Magnum/Trade/ImageData.h +++ b/src/Magnum/Trade/ImageData.h @@ -68,18 +68,23 @@ template class ImageData { * The data are expected to be of proper size for given @p storage * parameters. */ - explicit ImageData(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr); + explicit ImageData(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr) noexcept; /** @overload * Similar to the above, but uses default @ref PixelStorage parameters. */ - explicit ImageData(PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr): ImageData{{}, format, type, size, std::move(data), importerState} {} + explicit ImageData(PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr) noexcept: ImageData{{}, format, type, size, std::move(data), importerState} {} #ifdef MAGNUM_BUILD_DEPRECATED /** @copybrief ImageData(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&, const void*) * @deprecated Use @ref ImageData(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&, const void*) instead. */ - explicit CORRADE_DEPRECATED("use ImageData(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&) instead") ImageData(PixelFormat format, PixelType type, const VectorTypeFor& size, void* data): ImageData{format, type, size, Containers::Array{reinterpret_cast(data), Magnum::Implementation::imageDataSizeFor(format, type, size)}} {} + explicit CORRADE_DEPRECATED("use ImageData(PixelFormat, PixelType, const VectorTypeFor&, Containers::Array&&) instead") ImageData(PixelFormat format, PixelType type, const VectorTypeFor& size, void* data) noexcept: ImageData{format, type, size, Containers::Array{reinterpret_cast(data), Magnum::Implementation::imageDataSizeFor(format, type, size)}} {} + #ifndef DOXYGEN_GENERATING_OUTPUT + /* To avoid decay of nullptr to const void* and unwanted use of + deprecated function */ + explicit ImageData(PixelFormat format, PixelType type, const VectorTypeFor& size, std::nullptr_t) noexcept: ImageData{{}, format, type, size, nullptr} {} + #endif #endif #ifndef MAGNUM_TARGET_GLES @@ -97,7 +102,7 @@ template class ImageData { * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * WebGL. */ - explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr); + explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr) noexcept; #endif /** @@ -110,7 +115,7 @@ template class ImageData { * Similar the above, but uses default @ref CompressedPixelStorage * parameters (or the hardcoded ones in OpenGL ES and WebGL). */ - explicit ImageData(CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr); + explicit ImageData(CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr) noexcept; /** @brief Copying is not allowed */ ImageData(const ImageData&) = delete; @@ -210,7 +215,7 @@ template class ImageData { * @ref PixelStorage::dataProperties() for more information. * @see @ref isCompressed() */ - std::tuple, std::size_t> dataProperties() const; + std::tuple, VectorTypeFor, std::size_t> dataProperties() const; /* compressed data properties are not available because the importers are not setting any block size pixel storage properties to avoid @@ -221,10 +226,24 @@ template class ImageData { * * @see @ref release() */ - Containers::ArrayView data() { return _data; } + Containers::ArrayView data() + #ifndef CORRADE_GCC47_COMPATIBILITY + & + #endif + { return _data; } + #ifndef CORRADE_GCC47_COMPATIBILITY + Containers::ArrayView data() && = delete; /**< @overload */ + #endif /** @overload */ - Containers::ArrayView data() const { return _data; } + Containers::ArrayView data() const + #ifndef CORRADE_GCC47_COMPATIBILITY + & + #endif + { return _data; } + #ifndef CORRADE_GCC47_COMPATIBILITY + Containers::ArrayView data() const && = delete; /**< @overload */ + #endif /** @overload */ template T* data() { @@ -283,14 +302,14 @@ template ImageData::ImageData( #ifndef MAGNUM_TARGET_GLES const CompressedPixelStorage storage, #endif - const CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* importerState): _compressed{true}, + const CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* importerState) noexcept: _compressed{true}, #ifndef MAGNUM_TARGET_GLES _compressedStorage{storage}, #endif _compressedFormat{format}, _size{size}, _data{std::move(data)}, _importerState{importerState} {} #ifndef MAGNUM_TARGET_GLES -template inline ImageData::ImageData(const CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* const importerState): ImageData{{}, format, size, std::move(data), importerState} {} +template inline ImageData::ImageData(const CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* const importerState) noexcept: ImageData{{}, format, size, std::move(data), importerState} {} #endif template inline ImageData::ImageData(ImageData&& other) noexcept: _compressed{std::move(other._compressed)}, _size{std::move(other._size)}, _data{std::move(other._data)}, _importerState{std::move(other._importerState)} { diff --git a/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.h b/src/Magnum/Trade/LightData.cpp similarity index 65% rename from src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.h rename to src/Magnum/Trade/LightData.cpp index 1d6fba46c..68c04b0e6 100644 --- a/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.h +++ b/src/Magnum/Trade/LightData.cpp @@ -1,5 +1,3 @@ -#ifndef Magnum_MeshTools_Test_SubdivideRemoveDuplicatesBenchmark_h -#define Magnum_MeshTools_Test_SubdivideRemoveDuplicatesBenchmark_h /* This file is part of Magnum. @@ -25,26 +23,24 @@ DEALINGS IN THE SOFTWARE. */ -#include +#include "LightData.h" -#include "Magnum/Magnum.h" +namespace Magnum { namespace Trade { -namespace Magnum { namespace MeshTools { namespace Test { - -class SubdivideRemoveDuplicatesBenchmark: public QObject { - Q_OBJECT - - private slots: - void subdivide(); - void subdivideAndRemoveDuplicatesMeshAfter(); - void subdivideAndRemoveDuplicatesMeshBetween(); - - private: - static Magnum::Vector4 interpolator(const Magnum::Vector4& a, const Magnum::Vector4& b) { - return (a+b).xyz().normalized(); - } -}; - -}}} +#ifndef DOXYGEN_GENERATING_OUTPUT +Debug& operator<<(Debug& debug, const LightData::Type value) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case LightData::Type::value: return debug << "Trade::LightData::Type::" #value; + _c(Infinite) + _c(Point) + _c(Spot) + #undef _c + /* LCOV_EXCL_STOP */ + } + return debug << "Trade::LightData::Type(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; +} #endif + +}} diff --git a/src/Magnum/Trade/LightData.h b/src/Magnum/Trade/LightData.h index 3a8163f6d..636491a51 100644 --- a/src/Magnum/Trade/LightData.h +++ b/src/Magnum/Trade/LightData.h @@ -29,14 +29,85 @@ * @brief Class @ref Magnum::Trade::LightData */ -#include +#include "Magnum/Magnum.h" +#include "Magnum/Math/Color.h" namespace Magnum { namespace Trade { /** @brief Light data */ -class LightData {}; +class LightData { + public: + /** + * @brief Light type + * + * @see @ref type() + */ + enum class Type: UnsignedByte { + /** + * Light at position that is infinitely far away so its rays are + * parallel. The light rays point in a direction of negative Z + * axis. + */ + Infinite, + + /** Point light, radiating in all directions */ + Point, + + /** + * Spot light, radiating in a limited range of direction. The + * primary direction is negative Z axis. + */ + Spot + }; + + /** + * @brief Constructor + * @param type Light type + * @param color Light color + * @param intensity Light intensity + * @param importerState Importer-specific state + */ + constexpr explicit LightData(Type type, const Color3& color, Float intensity, const void* importerState = nullptr) noexcept: _type{type}, _color{color}, _intensity{intensity}, _importerState{importerState} {} + + /** @brief Copying is not allowed */ + LightData(const LightData&) = delete; + + /** @brief Move constructor */ + LightData(LightData&&) noexcept = default; + + /** @brief Copying is not allowed */ + LightData& operator=(const LightData&) = delete; + + /** @brief Move assignment */ + LightData& operator=(LightData&&) noexcept = default; + + /** @brief Light type */ + constexpr Type type() const { return _type; } + + /** @brief Light color */ + constexpr Color3 color() const { return _color; } + + /** @brief Light intensity */ + constexpr Float intensity() const { return _intensity; } + + /** + * @brief Importer-specific state + * + * See @ref AbstractImporter::importerState() for more information. + */ + const void* importerState() const { return _importerState; } + + private: + Type _type; + Vector3 _color; + Float _intensity; + const void* _importerState; +}; + +/** @debugoperatorenum{Magnum::Trade::LightData::Type} */ +MAGNUM_EXPORT Debug& operator<<(Debug& debug, LightData::Type value); }} diff --git a/src/Magnum/Trade/MeshData2D.cpp b/src/Magnum/Trade/MeshData2D.cpp index 0793d63a3..2e986ced1 100644 --- a/src/Magnum/Trade/MeshData2D.cpp +++ b/src/Magnum/Trade/MeshData2D.cpp @@ -33,11 +33,19 @@ MeshData2D::MeshData2D(const MeshPrimitive primitive, std::vector i CORRADE_ASSERT(!_positions.empty(), "Trade::MeshData2D: no position array specified", ); } -MeshData2D::MeshData2D(MeshData2D&&) = default; +MeshData2D::MeshData2D(MeshData2D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; MeshData2D::~MeshData2D() = default; -MeshData2D& MeshData2D::operator=(MeshData2D&&) = default; +MeshData2D& MeshData2D::operator=(MeshData2D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; std::vector& MeshData2D::indices() { CORRADE_ASSERT(isIndexed(), "Trade::MeshData2D::indices(): the mesh is not indexed", _indices); diff --git a/src/Magnum/Trade/MeshData2D.h b/src/Magnum/Trade/MeshData2D.h index 69946251f..30bc4b4d6 100644 --- a/src/Magnum/Trade/MeshData2D.h +++ b/src/Magnum/Trade/MeshData2D.h @@ -62,7 +62,14 @@ class MAGNUM_EXPORT MeshData2D { MeshData2D(const MeshData2D&) = delete; /** @brief Move constructor */ - MeshData2D(MeshData2D&&); + MeshData2D(MeshData2D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; ~MeshData2D(); @@ -70,7 +77,14 @@ class MAGNUM_EXPORT MeshData2D { MeshData2D& operator=(const MeshData2D&) = delete; /** @brief Move assignment */ - MeshData2D& operator=(MeshData2D&&); + MeshData2D& operator=(MeshData2D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Primitive */ MeshPrimitive primitive() const { return _primitive; } diff --git a/src/Magnum/Trade/MeshData3D.cpp b/src/Magnum/Trade/MeshData3D.cpp index 393584993..72d190930 100644 --- a/src/Magnum/Trade/MeshData3D.cpp +++ b/src/Magnum/Trade/MeshData3D.cpp @@ -33,11 +33,19 @@ MeshData3D::MeshData3D(const MeshPrimitive primitive, std::vector i CORRADE_ASSERT(!_positions.empty(), "Trade::MeshData3D: no position array specified", ); } -MeshData3D::MeshData3D(MeshData3D&&) = default; +MeshData3D::MeshData3D(MeshData3D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; MeshData3D::~MeshData3D() = default; -MeshData3D& MeshData3D::operator=(MeshData3D&&) = default; +MeshData3D& MeshData3D::operator=(MeshData3D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; std::vector& MeshData3D::indices() { CORRADE_ASSERT(isIndexed(), "Trade::MeshData3D::indices(): the mesh is not indexed", _indices); diff --git a/src/Magnum/Trade/MeshData3D.h b/src/Magnum/Trade/MeshData3D.h index 060f78bdd..0f800f2e2 100644 --- a/src/Magnum/Trade/MeshData3D.h +++ b/src/Magnum/Trade/MeshData3D.h @@ -63,7 +63,14 @@ class MAGNUM_EXPORT MeshData3D { MeshData3D(const MeshData3D&) = delete; /** @brief Move constructor */ - MeshData3D(MeshData3D&&); + MeshData3D(MeshData3D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; ~MeshData3D(); @@ -71,7 +78,14 @@ class MAGNUM_EXPORT MeshData3D { MeshData3D& operator=(const MeshData3D&) = delete; /** @brief Move assignment */ - MeshData3D& operator=(MeshData3D&&); + MeshData3D& operator=(MeshData3D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Primitive */ MeshPrimitive primitive() const { return _primitive; } diff --git a/src/Magnum/Trade/MeshObjectData2D.h b/src/Magnum/Trade/MeshObjectData2D.h index 26dad47c5..7ef931d6e 100644 --- a/src/Magnum/Trade/MeshObjectData2D.h +++ b/src/Magnum/Trade/MeshObjectData2D.h @@ -57,13 +57,27 @@ class MAGNUM_EXPORT MeshObjectData2D: public ObjectData2D { MeshObjectData2D(const MeshObjectData2D&) = delete; /** @brief Move constructor */ - MeshObjectData2D(MeshObjectData2D&&) = default; + MeshObjectData2D(MeshObjectData2D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; /** @brief Copying is not allowed */ MeshObjectData2D& operator=(const MeshObjectData2D&) = delete; /** @brief Move assignment */ - MeshObjectData2D& operator=(MeshObjectData2D&&) = default; + MeshObjectData2D& operator=(MeshObjectData2D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; /** * @brief Material ID diff --git a/src/Magnum/Trade/MeshObjectData3D.h b/src/Magnum/Trade/MeshObjectData3D.h index 305b74d36..96e6dbc37 100644 --- a/src/Magnum/Trade/MeshObjectData3D.h +++ b/src/Magnum/Trade/MeshObjectData3D.h @@ -57,13 +57,27 @@ class MAGNUM_EXPORT MeshObjectData3D: public ObjectData3D { MeshObjectData3D(const MeshObjectData3D&) = delete; /** @brief Move constructor */ - MeshObjectData3D(MeshObjectData3D&&) = default; + MeshObjectData3D(MeshObjectData3D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; /** @brief Copying is not allowed */ MeshObjectData3D& operator=(const MeshObjectData3D&) = delete; /** @brief Move assignment */ - MeshObjectData3D& operator=(MeshObjectData3D&&) = default; + MeshObjectData3D& operator=(MeshObjectData3D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; /** * @brief Material ID diff --git a/src/Magnum/Trade/ObjectData2D.cpp b/src/Magnum/Trade/ObjectData2D.cpp index 4ea19c029..08b182331 100644 --- a/src/Magnum/Trade/ObjectData2D.cpp +++ b/src/Magnum/Trade/ObjectData2D.cpp @@ -31,23 +31,33 @@ ObjectData2D::ObjectData2D(std::vector children, const Matrix3& tra ObjectData2D::ObjectData2D(std::vector children, const Matrix3& transformation, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{ObjectInstanceType2D::Empty}, _instance{-1}, _importerState{importerState} {} -ObjectData2D::ObjectData2D(ObjectData2D&&) = default; +ObjectData2D::ObjectData2D(ObjectData2D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; ObjectData2D::~ObjectData2D() = default; -ObjectData2D& ObjectData2D::operator=(ObjectData2D&&) = default; +ObjectData2D& ObjectData2D::operator=(ObjectData2D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, ObjectInstanceType2D value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case ObjectInstanceType2D::value: return debug << "Trade::ObjectInstanceType2D::" #value; _c(Camera) _c(Mesh) _c(Empty) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Trade::ObjectInstanceType2D::(invalid)"; + return debug << "Trade::ObjectInstanceType2D(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/Trade/ObjectData2D.h b/src/Magnum/Trade/ObjectData2D.h index 01b3cd2b2..589119984 100644 --- a/src/Magnum/Trade/ObjectData2D.h +++ b/src/Magnum/Trade/ObjectData2D.h @@ -83,7 +83,14 @@ class MAGNUM_EXPORT ObjectData2D { ObjectData2D(const ObjectData2D&) = delete; /** @brief Move constructor */ - ObjectData2D(ObjectData2D&&); + ObjectData2D(ObjectData2D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Destructor */ virtual ~ObjectData2D(); @@ -92,7 +99,14 @@ class MAGNUM_EXPORT ObjectData2D { ObjectData2D& operator=(const ObjectData2D&) = delete; /** @brief Move assignment */ - ObjectData2D& operator=(ObjectData2D&&); + ObjectData2D& operator=(ObjectData2D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Child objects */ std::vector& children() { return _children; } @@ -110,8 +124,10 @@ class MAGNUM_EXPORT ObjectData2D { /** * @brief Instance ID - * @return ID of given camera / light / mesh etc., specified by - * @ref instanceType() + * + * Returns ID of given camera / light / mesh etc., specified by + * @ref instanceType(). If @ref instanceType() is + * @ref ObjectInstanceType2D::Empty, this function returns `-1`. */ Int instance() const { return _instance; } diff --git a/src/Magnum/Trade/ObjectData3D.cpp b/src/Magnum/Trade/ObjectData3D.cpp index c0e0cfc94..0a1d2c843 100644 --- a/src/Magnum/Trade/ObjectData3D.cpp +++ b/src/Magnum/Trade/ObjectData3D.cpp @@ -31,24 +31,34 @@ ObjectData3D::ObjectData3D(std::vector children, const Matrix4& tra ObjectData3D::ObjectData3D(std::vector children, const Matrix4& transformation, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{ObjectInstanceType3D::Empty}, _instance{-1}, _importerState{importerState} {} -ObjectData3D::ObjectData3D(ObjectData3D&&) = default; +ObjectData3D::ObjectData3D(ObjectData3D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; ObjectData3D::~ObjectData3D() = default; -ObjectData3D& ObjectData3D::operator=(ObjectData3D&&) = default; +ObjectData3D& ObjectData3D::operator=(ObjectData3D&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, ObjectInstanceType3D value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case ObjectInstanceType3D::value: return debug << "Trade::ObjectInstanceType3D::" #value; _c(Camera) _c(Light) _c(Mesh) _c(Empty) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Trade::ObjectInstanceType3D::(invalid)"; + return debug << "Trade::ObjectInstanceType3D(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/Trade/ObjectData3D.h b/src/Magnum/Trade/ObjectData3D.h index 382615bc1..042a91acf 100644 --- a/src/Magnum/Trade/ObjectData3D.h +++ b/src/Magnum/Trade/ObjectData3D.h @@ -42,8 +42,8 @@ namespace Magnum { namespace Trade { @see @ref ObjectData3D::instanceType() */ enum class ObjectInstanceType3D: UnsignedByte { - Camera, /**< Camera instance (see CameraData) */ - Light, /**< Light instance (see LightData) */ + Camera, /**< Camera instance (see @ref CameraData) */ + Light, /**< Light instance (see @ref LightData) */ /** * Mesh instance. The data can be cast to @ref MeshObjectData3D to provide @@ -54,7 +54,6 @@ enum class ObjectInstanceType3D: UnsignedByte { Empty /**< Empty */ }; - /** @brief Three-dimensional object data @@ -85,7 +84,14 @@ class MAGNUM_EXPORT ObjectData3D { ObjectData3D(const ObjectData3D&) = delete; /** @brief Move constructor */ - ObjectData3D(ObjectData3D&&); + ObjectData3D(ObjectData3D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Destructor */ virtual ~ObjectData3D(); @@ -94,7 +100,14 @@ class MAGNUM_EXPORT ObjectData3D { ObjectData3D& operator=(const ObjectData3D&) = delete; /** @brief Move assignment */ - ObjectData3D& operator=(ObjectData3D&&); + ObjectData3D& operator=(ObjectData3D&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Child objects */ std::vector& children() { return _children; } diff --git a/src/Magnum/Trade/PhongMaterialData.cpp b/src/Magnum/Trade/PhongMaterialData.cpp index ff427d677..2d8423ea2 100644 --- a/src/Magnum/Trade/PhongMaterialData.cpp +++ b/src/Magnum/Trade/PhongMaterialData.cpp @@ -27,7 +27,48 @@ namespace Magnum { namespace Trade { -Vector3& PhongMaterialData::ambientColor() { +PhongMaterialData::PhongMaterialData(PhongMaterialData&& other) noexcept: AbstractMaterialData{std::move(other)}, _flags{std::move(other._flags)}, _shininess{std::move(other._shininess)} { + if(_flags & Flag::AmbientTexture) + _ambient.texture = other._ambient.texture; + else + _ambient.color = other._ambient.color; + + if(_flags & Flag::DiffuseTexture) + _diffuse.texture = other._diffuse.texture; + else + _diffuse.color = other._diffuse.color; + + if(_flags & Flag::SpecularTexture) + _specular.texture = other._specular.texture; + else + _specular.color = other._specular.color; +} + +PhongMaterialData& PhongMaterialData::operator=(PhongMaterialData&& other) noexcept { + AbstractMaterialData::operator=(std::move(other)); + + _flags = other._flags; + _shininess = other._shininess; + + if(_flags & Flag::AmbientTexture) + _ambient.texture = other._ambient.texture; + else + _ambient.color = other._ambient.color; + + if(_flags & Flag::DiffuseTexture) + _diffuse.texture = other._diffuse.texture; + else + _diffuse.color = other._diffuse.color; + + if(_flags & Flag::SpecularTexture) + _specular.texture = other._specular.texture; + else + _specular.color = other._specular.color; + + return *this; +} + +Color3& PhongMaterialData::ambientColor() { CORRADE_ASSERT(!(_flags & Flag::AmbientTexture), "Trade::PhongMaterialData::ambientColor(): the material has ambient texture", _ambient.color); return _ambient.color; } @@ -37,7 +78,7 @@ UnsignedInt& PhongMaterialData::ambientTexture() { return _ambient.texture; } -Vector3& PhongMaterialData::diffuseColor() { +Color3& PhongMaterialData::diffuseColor() { CORRADE_ASSERT(!(_flags & Flag::DiffuseTexture), "Trade::PhongMaterialData::diffuseColor(): the material has diffuse texture", _diffuse.color); return _diffuse.color; } @@ -47,7 +88,7 @@ UnsignedInt& PhongMaterialData::diffuseTexture() { return _diffuse.texture; } -Vector3& PhongMaterialData::specularColor() { +Color3& PhongMaterialData::specularColor() { CORRADE_ASSERT(!(_flags & Flag::SpecularTexture), "Trade::PhongMaterialData::specularColor(): the material has specular texture", _specular.color); return _specular.color; } diff --git a/src/Magnum/Trade/PhongMaterialData.h b/src/Magnum/Trade/PhongMaterialData.h index dee266602..3bc231175 100644 --- a/src/Magnum/Trade/PhongMaterialData.h +++ b/src/Magnum/Trade/PhongMaterialData.h @@ -30,7 +30,7 @@ */ #include "Magnum/Magnum.h" -#include "Magnum/Math/Vector3.h" +#include "Magnum/Math/Color.h" #include "Magnum/Trade/AbstractMaterialData.h" namespace Magnum { namespace Trade { @@ -73,7 +73,19 @@ class MAGNUM_EXPORT PhongMaterialData: public AbstractMaterialData { * Colors and textures should be specified using member functions based * on what flags are set. */ - explicit PhongMaterialData(Flags flags, Float shininess, const void* importerState = nullptr): AbstractMaterialData{MaterialType::Phong, importerState}, _shininess{shininess}, _flags{flags} {} + explicit PhongMaterialData(Flags flags, Float shininess, const void* importerState = nullptr) noexcept: AbstractMaterialData{MaterialType::Phong, importerState}, _flags{flags}, _shininess{shininess} {} + + /** @brief Copying is not allowed */ + PhongMaterialData(const PhongMaterialData&) = delete; + + /** @brief Move constructor */ + PhongMaterialData(PhongMaterialData&& other) noexcept; + + /** @brief Copying is not allowed */ + PhongMaterialData& operator=(const PhongMaterialData&) = delete; + + /** @brief Move assignment */ + PhongMaterialData& operator=(PhongMaterialData&& other) noexcept; /** @brief Material flags */ Flags flags() const { return _flags; } @@ -84,8 +96,8 @@ class MAGNUM_EXPORT PhongMaterialData: public AbstractMaterialData { * Available only if the material doesn't have @ref Flag::AmbientTexture. * @see @ref flags() */ - Vector3& ambientColor(); - Vector3 ambientColor() const; /**< @overload */ + Color3& ambientColor(); + Color3 ambientColor() const; /**< @overload */ /** * @brief Ambient texture ID @@ -102,8 +114,8 @@ class MAGNUM_EXPORT PhongMaterialData: public AbstractMaterialData { * Available only if the material doesn't have @ref Flag::DiffuseTexture. * @see @ref flags() */ - Vector3& diffuseColor(); - Vector3 diffuseColor() const; /**< @overload */ + Color3& diffuseColor(); + Color3 diffuseColor() const; /**< @overload */ /** * @brief Diffuse texture ID @@ -120,8 +132,8 @@ class MAGNUM_EXPORT PhongMaterialData: public AbstractMaterialData { * Available only if the material doesn't have @ref Flag::SpecularTexture. * @see @ref flags() */ - Vector3& specularColor(); - Vector3 specularColor() const; /**< @overload */ + Color3& specularColor(); + Color3 specularColor() const; /**< @overload */ /** * @brief Specular texture ID @@ -139,22 +151,22 @@ class MAGNUM_EXPORT PhongMaterialData: public AbstractMaterialData { union Source { Source() {} - Vector3 color; + Color3 color; UnsignedInt texture; }; + Flags _flags; + Float _shininess; Source _ambient, _diffuse, _specular; - Float _shininess; - Flags _flags; }; CORRADE_ENUMSET_OPERATORS(PhongMaterialData::Flags) /* Ugly as hell. */ -inline Vector3 PhongMaterialData::ambientColor() const { +inline Color3 PhongMaterialData::ambientColor() const { return const_cast(this)->ambientColor(); } @@ -162,7 +174,7 @@ inline UnsignedInt PhongMaterialData::ambientTexture() const { return const_cast(this)->ambientTexture(); } -inline Vector3 PhongMaterialData::diffuseColor() const { +inline Color3 PhongMaterialData::diffuseColor() const { return const_cast(this)->diffuseColor(); } @@ -170,7 +182,7 @@ inline UnsignedInt PhongMaterialData::diffuseTexture() const { return const_cast(this)->diffuseTexture(); } -inline Vector3 PhongMaterialData::specularColor() const { +inline Color3 PhongMaterialData::specularColor() const { return const_cast(this)->specularColor(); } diff --git a/src/Magnum/Trade/SceneData.cpp b/src/Magnum/Trade/SceneData.cpp index f00726a0b..9b656e9dd 100644 --- a/src/Magnum/Trade/SceneData.cpp +++ b/src/Magnum/Trade/SceneData.cpp @@ -29,8 +29,16 @@ namespace Magnum { namespace Trade { SceneData::SceneData(std::vector children2D, std::vector children3D, const void* const importerState): _children2D{std::move(children2D)}, _children3D{std::move(children3D)}, _importerState{importerState} {} -SceneData::SceneData(SceneData&&) = default; - -SceneData& SceneData::operator=(SceneData&&) = default; +SceneData::SceneData(SceneData&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; + +SceneData& SceneData::operator=(SceneData&&) + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + = default; }} diff --git a/src/Magnum/Trade/SceneData.h b/src/Magnum/Trade/SceneData.h index 0c12bb7f0..d6707ae32 100644 --- a/src/Magnum/Trade/SceneData.h +++ b/src/Magnum/Trade/SceneData.h @@ -54,13 +54,27 @@ class MAGNUM_EXPORT SceneData { SceneData(const SceneData&) = delete; /** @brief Move constructor */ - SceneData(SceneData&&); + SceneData(SceneData&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Copying is not allowed */ SceneData& operator=(const SceneData&) = delete; /** @brief Move assignment */ - SceneData& operator=(SceneData&&); + SceneData& operator=(SceneData&&) + /* GCC 4.9.0 (the one from Android NDK) thinks this does not match + the implicit signature so it can't be defaulted. Works on 4.7, + 5.0 and everywhere else, so I don't bother. */ + #if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409 + noexcept + #endif + ; /** @brief Two-dimensional child objects */ const std::vector& children2D() const { return _children2D; } diff --git a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp index fc2b86f2e..a081a262c 100644 --- a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp @@ -25,12 +25,14 @@ #include #include +#include #include #include #include "Magnum/ImageView.h" #include "Magnum/PixelFormat.h" #include "Magnum/Trade/AbstractImageConverter.h" +#include "Magnum/Trade/ImageData.h" #include "configure.h" @@ -41,10 +43,19 @@ class AbstractImageConverterTest: public TestSuite::Tester { explicit AbstractImageConverterTest(); void exportToFile(); + + void exportToDataImageData(); + void exportToFileImageData(); }; AbstractImageConverterTest::AbstractImageConverterTest() { - addTests({&AbstractImageConverterTest::exportToFile}); + addTests({&AbstractImageConverterTest::exportToFile, + + &AbstractImageConverterTest::exportToDataImageData, + &AbstractImageConverterTest::exportToFileImageData}); + + /* Create testing dir */ + Utility::Directory::mkpath(TRADE_TEST_OUTPUT_DIR); } void AbstractImageConverterTest::exportToFile() { @@ -68,6 +79,59 @@ void AbstractImageConverterTest::exportToFile() { "\xFE\xED", TestSuite::Compare::FileToString); } +namespace { + +class ImageDataExporter: public Trade::AbstractImageConverter { + private: + Features doFeatures() const override { return Feature::ConvertData; } + + Containers::Array doExportToData(const ImageView2D&) override { + return Containers::Array::from('B'); + }; + + Containers::Array doExportToData(const CompressedImageView2D&) override { + return Containers::Array::from('C'); + }; +}; + +} + +void AbstractImageConverterTest::exportToDataImageData() { + ImageDataExporter exporter; + + { + /* Should get "B" when converting uncompressed */ + ImageData2D image{PixelFormat::RGBA, PixelType::UnsignedByte, {}, nullptr}; + CORRADE_COMPARE_AS(exporter.exportToData(image), + Containers::Array::from('B'), + TestSuite::Compare::Container); + } { + /* Should get "C" when converting compressed */ + ImageData2D image{PixelFormat::RGBA, PixelType::UnsignedByte, {}, nullptr}; + CORRADE_COMPARE_AS(exporter.exportToData(image), + Containers::Array::from('B'), + TestSuite::Compare::Container); + } +} + +void AbstractImageConverterTest::exportToFileImageData() { + ImageDataExporter exporter; + + { + /* Should get "B" when converting uncompressed */ + ImageData2D image{PixelFormat::RGBA, PixelType::UnsignedByte, {}, nullptr}; + CORRADE_VERIFY(exporter.exportToFile(image, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "B", TestSuite::Compare::FileToString); + } { + /* Should get "B" when converting uncompressed */ + ImageData2D image{PixelFormat::RGBA, PixelType::UnsignedByte, {}, nullptr}; + CORRADE_VERIFY(exporter.exportToFile(image, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "B", TestSuite::Compare::FileToString); + } +} + }}} CORRADE_TEST_MAIN(Magnum::Trade::Test::AbstractImageConverterTest) diff --git a/src/Magnum/Trade/Test/CMakeLists.txt b/src/Magnum/Trade/Test/CMakeLists.txt index ffe52e9c9..9db022173 100644 --- a/src/Magnum/Trade/Test/CMakeLists.txt +++ b/src/Magnum/Trade/Test/CMakeLists.txt @@ -23,15 +23,30 @@ # DEALINGS IN THE SOFTWARE. # +if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) + set(TRADE_TEST_DIR ".") + set(TRADE_TEST_OUTPUT_DIR "./write") +else() + set(TRADE_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + set(TRADE_TEST_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure.h) corrade_add_test(TradeAbstractImageConverterTest AbstractImageConverterTest.cpp LIBRARIES Magnum) target_include_directories(TradeAbstractImageConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -corrade_add_test(TradeAbstractImporterTest AbstractImporterTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeAbstractImporterTest AbstractImporterTest.cpp + LIBRARIES Magnum + FILES file.bin) target_include_directories(TradeAbstractImporterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -corrade_add_test(TradeAbstractMaterialDataTest AbstractMaterialDataTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeCameraDataTest CameraDataTest.cpp LIBRARIES Magnum) corrade_add_test(TradeImageDataTest ImageDataTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeLightDataTest LightDataTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeMaterialDataTest MaterialDataTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeMeshData2DTest MeshData2DTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeMeshData3DTest MeshData3DTest.cpp LIBRARIES Magnum) corrade_add_test(TradeObjectData2DTest ObjectData2DTest.cpp LIBRARIES Magnum) corrade_add_test(TradeObjectData3DTest ObjectData3DTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeSceneDataTest SceneDataTest.cpp LIBRARIES Magnum) corrade_add_test(TradeTextureDataTest TextureDataTest.cpp LIBRARIES Magnum) diff --git a/src/Magnum/Trade/Test/CameraDataTest.cpp b/src/Magnum/Trade/Test/CameraDataTest.cpp new file mode 100644 index 000000000..be7ae405b --- /dev/null +++ b/src/Magnum/Trade/Test/CameraDataTest.cpp @@ -0,0 +1,121 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Trade/CameraData.h" + +namespace Magnum { namespace Trade { namespace Test { + +struct CameraDataTest: TestSuite::Tester { + explicit CameraDataTest(); + + void construct(); + void constructDefaults(); + void constructCopy(); + void constructMove(); +}; + +namespace { + +using namespace Math::Literals; + +enum: std::size_t { ConstructDefaultsDataCount = 3 }; + +struct { + const char* name; + Rad fov, expectedFov; + Float near, expectedNear; + Float far, expectedFar; +} ConstructDefaultsData[ConstructDefaultsDataCount]{ + {"fov", Rad{Constants::nan()}, 35.0_degf, 0.5f, 0.5f, 120.0f, 120.0f}, + {"near", 25.0_degf, 25.0_degf, Constants::nan(), 0.01f, 120.0f, 120.0f}, + {"far", 25.0_degf, 25.0_degf, 0.5f, 0.5f, Constants::nan(), 100.0f} +}; + +} + +CameraDataTest::CameraDataTest() { + addTests({&CameraDataTest::construct}); + + addInstancedTests({&CameraDataTest::constructDefaults}, ConstructDefaultsDataCount); + + addTests({&CameraDataTest::constructCopy, + &CameraDataTest::constructMove}); +} + +void CameraDataTest::construct() { + const int a{}; + CameraData data{25.0_degf, 0.001f, 1000.0f, &a}; + + CORRADE_COMPARE(data.fov(), 25.0_degf); + CORRADE_COMPARE(data.near(), 0.001f); + CORRADE_COMPARE(data.far(), 1000.0f); + CORRADE_COMPARE(data.importerState(), &a); +} + +void CameraDataTest::constructDefaults() { + setTestCaseDescription(ConstructDefaultsData[testCaseInstanceId()].name); + + const int a{}; + CameraData data{ + ConstructDefaultsData[testCaseInstanceId()].fov, + ConstructDefaultsData[testCaseInstanceId()].near, + ConstructDefaultsData[testCaseInstanceId()].far, + &a}; + + CORRADE_COMPARE(data.fov(), ConstructDefaultsData[testCaseInstanceId()].expectedFov); + CORRADE_COMPARE(data.near(), ConstructDefaultsData[testCaseInstanceId()].expectedNear); + CORRADE_COMPARE(data.far(), ConstructDefaultsData[testCaseInstanceId()].expectedFar); + CORRADE_COMPARE(data.importerState(), &a); +} + +void CameraDataTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void CameraDataTest::constructMove() { + const int a{}; + CameraData data{25.0_degf, 0.001f, 1000.0f, &a}; + + CameraData b{std::move(data)}; + CORRADE_COMPARE(b.fov(), 25.0_degf); + CORRADE_COMPARE(b.near(), 0.001f); + CORRADE_COMPARE(b.far(), 1000.0f); + CORRADE_COMPARE(b.importerState(), &a); + + const int c{}; + CameraData d{75.0_degf, 0.5f, 10.0f, &c}; + d = std::move(b); + CORRADE_COMPARE(d.fov(), 25.0_degf); + CORRADE_COMPARE(d.near(), 0.001f); + CORRADE_COMPARE(d.far(), 1000.0f); + CORRADE_COMPARE(d.importerState(), &a); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::CameraDataTest) diff --git a/src/Magnum/Trade/Test/ImageDataTest.cpp b/src/Magnum/Trade/Test/ImageDataTest.cpp index f56132e60..ed8674b93 100644 --- a/src/Magnum/Trade/Test/ImageDataTest.cpp +++ b/src/Magnum/Trade/Test/ImageDataTest.cpp @@ -60,13 +60,13 @@ ImageDataTest::ImageDataTest() { } void ImageDataTest::construct() { - auto data = new char[3]; + auto data = new char[3*3]; Trade::ImageData2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3}}; + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; CORRADE_VERIFY(!a.isCompressed()); CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::Red); + CORRADE_COMPARE(a.format(), PixelFormat::RGB); CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); CORRADE_COMPARE(a.size(), Vector2i(1, 3)); CORRADE_COMPARE(a.data(), data); @@ -96,9 +96,9 @@ void ImageDataTest::constructCopy() { } void ImageDataTest::constructMove() { - auto data = new char[3]; + auto data = new char[3*3]; Trade::ImageData2D a{PixelStorage{}.setAlignment(1), - PixelFormat::Red, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3}}; + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; Trade::ImageData2D b(std::move(a)); CORRADE_COMPARE(a.data(), nullptr); @@ -106,7 +106,7 @@ void ImageDataTest::constructMove() { CORRADE_VERIFY(!b.isCompressed()); CORRADE_COMPARE(b.storage().alignment(), 1); - CORRADE_COMPARE(b.format(), PixelFormat::Red); + CORRADE_COMPARE(b.format(), PixelFormat::RGB); CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.data(), data); @@ -120,7 +120,7 @@ void ImageDataTest::constructMove() { CORRADE_VERIFY(!c.isCompressed()); CORRADE_COMPARE(c.storage().alignment(), 1); - CORRADE_COMPARE(c.format(), PixelFormat::Red); + CORRADE_COMPARE(c.format(), PixelFormat::RGB); CORRADE_COMPARE(c.type(), PixelType::UnsignedByte); CORRADE_COMPARE(c.size(), Vector2i(1, 3)); CORRADE_COMPARE(c.data(), data); @@ -166,13 +166,15 @@ void ImageDataTest::constructMoveCompressed() { } void ImageDataTest::toView() { - auto data = new char[4]; - const Trade::ImageData2D a{PixelFormat::Red, PixelType::UnsignedByte, {4, 1}, Containers::Array{data, 4}}; + auto data = new char[3*3]; + const Trade::ImageData2D a{PixelStorage{}.setAlignment(1), + PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; ImageView2D b = a; - CORRADE_COMPARE(b.format(), PixelFormat::Red); + CORRADE_COMPARE(b.storage().alignment(), 1); + CORRADE_COMPARE(b.format(), PixelFormat::RGB); CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(b.size(), Vector2i(4, 1)); + CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.data(), data); } @@ -189,7 +191,7 @@ void ImageDataTest::toViewCompressed() { void ImageDataTest::release() { char data[] = {'b', 'e', 'e', 'r'}; - Trade::ImageData2D a{PixelFormat::Red, PixelType::UnsignedByte, {4, 1}, Containers::Array{data, 4}}; + Trade::ImageData2D a{PixelFormat::RGBA, PixelType::UnsignedByte, {1, 1}, Containers::Array{data, 4}}; const char* const pointer = a.release().release(); CORRADE_COMPARE(pointer, data); diff --git a/src/Magnum/Trade/Test/LightDataTest.cpp b/src/Magnum/Trade/Test/LightDataTest.cpp new file mode 100644 index 000000000..54d3e6381 --- /dev/null +++ b/src/Magnum/Trade/Test/LightDataTest.cpp @@ -0,0 +1,101 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Magnum/Trade/LightData.h" + +namespace Magnum { namespace Trade { namespace Test { + +struct LightDataTest: TestSuite::Tester { + explicit LightDataTest(); + + void construct(); + void constructCopy(); + void constructMove(); + + void debugType(); +}; + +LightDataTest::LightDataTest() { + addTests({&LightDataTest::construct, + &LightDataTest::constructCopy, + &LightDataTest::constructMove, + + &LightDataTest::debugType}); +} + +void LightDataTest::construct() { + using namespace Math::Literals; + const int a{}; + LightData data{LightData::Type::Infinite, 0xccff33_rgbf, 0.8f, &a}; + + CORRADE_COMPARE(data.type(), LightData::Type::Infinite); + CORRADE_COMPARE(data.color(), 0xccff33_rgbf); + CORRADE_COMPARE(data.intensity(), 0.8f); + CORRADE_COMPARE(data.importerState(), &a); +} + +void LightDataTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void LightDataTest::constructMove() { + using namespace Math::Literals; + const int a{}; + LightData data{LightData::Type::Infinite, 0xccff33_rgbf, 0.8f, &a}; + + CORRADE_COMPARE(data.type(), LightData::Type::Infinite); + CORRADE_COMPARE(data.color(), 0xccff33_rgbf); + CORRADE_COMPARE(data.intensity(), 0.8f); + CORRADE_COMPARE(data.importerState(), &a); + + LightData b{std::move(data)}; + CORRADE_COMPARE(b.type(), LightData::Type::Infinite); + CORRADE_COMPARE(b.color(), 0xccff33_rgbf); + CORRADE_COMPARE(b.intensity(), 0.8f); + CORRADE_COMPARE(b.importerState(), &a); + + const int c{}; + LightData d{LightData::Type::Point, 0xdead00_rgbf, 1.6f, &c}; + d = std::move(b); + CORRADE_COMPARE(d.type(), LightData::Type::Infinite); + CORRADE_COMPARE(d.color(), 0xccff33_rgbf); + CORRADE_COMPARE(d.intensity(), 0.8f); + CORRADE_COMPARE(d.importerState(), &a); +} + +void LightDataTest::debugType() { + std::ostringstream out; + + Debug(&out) << LightData::Type::Spot << LightData::Type(0xbe); + CORRADE_COMPARE(out.str(), "Trade::LightData::Type::Spot Trade::LightData::Type(0xbe)\n"); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::LightDataTest) diff --git a/src/Magnum/Trade/Test/MaterialDataTest.cpp b/src/Magnum/Trade/Test/MaterialDataTest.cpp new file mode 100644 index 000000000..1685bacd9 --- /dev/null +++ b/src/Magnum/Trade/Test/MaterialDataTest.cpp @@ -0,0 +1,243 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Magnum/Trade/PhongMaterialData.h" + +namespace Magnum { namespace Trade { namespace Test { + +class MaterialDataTest: public TestSuite::Tester { + public: + explicit MaterialDataTest(); + + void constructPhong(); + void constructPhongAmbientTexture(); + void constructPhongDiffuseTexture(); + void constructPhongSpecularTexture(); + void constructCopy(); + void constructMovePhongNoAmbientTexture(); + void constructMovePhongNoDiffuseTexture(); + void constructMovePhongNoSpecularTexture(); + + void debugType(); +}; + +MaterialDataTest::MaterialDataTest() { + addTests({&MaterialDataTest::constructPhong, + &MaterialDataTest::constructPhongAmbientTexture, + &MaterialDataTest::constructPhongDiffuseTexture, + &MaterialDataTest::constructPhongSpecularTexture, + &MaterialDataTest::constructCopy, + &MaterialDataTest::constructMovePhongNoAmbientTexture, + &MaterialDataTest::constructMovePhongNoDiffuseTexture, + &MaterialDataTest::constructMovePhongNoSpecularTexture, + + &MaterialDataTest::debugType}); +} + +void MaterialDataTest::constructPhong() { + using namespace Math::Literals; + + const int a{}; + PhongMaterialData data{{}, 80.0f, &a}; + data.ambientColor() = 0xccffbb_rgbf; + data.diffuseColor() = 0xeebbff_rgbf; + data.specularColor() = 0xacabad_rgbf; + + const PhongMaterialData& cdata = data; + + CORRADE_VERIFY(cdata.flags() == PhongMaterialData::Flags{}); + CORRADE_COMPARE(cdata.ambientColor(), 0xccffbb_rgbf); + CORRADE_COMPARE(cdata.diffuseColor(), 0xeebbff_rgbf); + CORRADE_COMPARE(cdata.specularColor(), 0xacabad_rgbf); + CORRADE_COMPARE(cdata.shininess(), 80.0f); +} + +void MaterialDataTest::constructPhongAmbientTexture() { + using namespace Math::Literals; + + const int a{}; + PhongMaterialData data{PhongMaterialData::Flag::AmbientTexture, 80.0f, &a}; + data.ambientTexture() = 42; + data.diffuseColor() = 0xeebbff_rgbf; + data.specularColor() = 0xacabad_rgbf; + + const PhongMaterialData& cdata = data; + + CORRADE_VERIFY(cdata.flags() == PhongMaterialData::Flag::AmbientTexture); + CORRADE_COMPARE(cdata.ambientTexture(), 42); + CORRADE_COMPARE(cdata.diffuseColor(), 0xeebbff_rgbf); + CORRADE_COMPARE(cdata.specularColor(), 0xacabad_rgbf); + CORRADE_COMPARE(cdata.shininess(), 80.0f); +} + +void MaterialDataTest::constructPhongDiffuseTexture() { + using namespace Math::Literals; + + const int a{}; + PhongMaterialData data{PhongMaterialData::Flag::DiffuseTexture, 80.0f, &a}; + data.ambientColor() = 0xccffbb_rgbf; + data.diffuseTexture() = 42; + data.specularColor() = 0xacabad_rgbf; + + const PhongMaterialData& cdata = data; + + CORRADE_VERIFY(cdata.flags() == PhongMaterialData::Flag::DiffuseTexture); + CORRADE_COMPARE(cdata.ambientColor(), 0xccffbb_rgbf); + CORRADE_COMPARE(cdata.diffuseTexture(), 42); + CORRADE_COMPARE(cdata.specularColor(), 0xacabad_rgbf); + CORRADE_COMPARE(cdata.shininess(), 80.0f); +} + +void MaterialDataTest::constructPhongSpecularTexture() { + using namespace Math::Literals; + + const int a{}; + PhongMaterialData data{PhongMaterialData::Flag::SpecularTexture, 30.0f, &a}; + data.ambientColor() = 0xccffbb_rgbf; + data.diffuseColor() = 0xeebbff_rgbf; + data.specularTexture() = 42; + + const PhongMaterialData& cdata = data; + + CORRADE_VERIFY(cdata.flags() == PhongMaterialData::Flag::SpecularTexture); + CORRADE_COMPARE(cdata.ambientColor(), 0xccffbb_rgbf); + CORRADE_COMPARE(cdata.diffuseColor(), 0xeebbff_rgbf); + CORRADE_COMPARE(cdata.specularTexture(), 42); + CORRADE_COMPARE(cdata.shininess(), 30.0f); +} + +void MaterialDataTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void MaterialDataTest::constructMovePhongNoAmbientTexture() { + using namespace Math::Literals; + + const int a{}; + PhongMaterialData data{PhongMaterialData::Flag::DiffuseTexture|PhongMaterialData::Flag::SpecularTexture, 80.0f, &a}; + data.ambientColor() = 0xccffbb_rgbf; + data.diffuseTexture() = 42; + data.specularTexture() = 13; + + PhongMaterialData b{std::move(data)}; + + CORRADE_VERIFY(b.flags() == (PhongMaterialData::Flag::DiffuseTexture|PhongMaterialData::Flag::SpecularTexture)); + CORRADE_COMPARE(b.ambientColor(), 0xccffbb_rgbf); + CORRADE_COMPARE(b.diffuseTexture(), 42); + CORRADE_COMPARE(b.specularTexture(), 13); + CORRADE_COMPARE(b.shininess(), 80.0f); + + const int c{}; + PhongMaterialData d{PhongMaterialData::Flag::AmbientTexture, 100.0f, &c}; + d.ambientTexture() = 42; + d.diffuseColor() = 0xeebbff_rgbf; + d.specularColor() = 0xacabad_rgbf; + d = std::move(b); + + CORRADE_VERIFY(d.flags() == (PhongMaterialData::Flag::DiffuseTexture|PhongMaterialData::Flag::SpecularTexture)); + CORRADE_COMPARE(d.ambientColor(), 0xccffbb_rgbf); + CORRADE_COMPARE(d.diffuseTexture(), 42); + CORRADE_COMPARE(d.specularTexture(), 13); + CORRADE_COMPARE(d.shininess(), 80.0f); +} + +void MaterialDataTest::constructMovePhongNoDiffuseTexture() { + using namespace Math::Literals; + + const int a{}; + PhongMaterialData data{PhongMaterialData::Flag::AmbientTexture|PhongMaterialData::Flag::SpecularTexture, 80.0f, &a}; + data.ambientTexture() = 42; + data.diffuseColor() = 0xeebbff_rgbf; + data.specularTexture() = 13; + + PhongMaterialData b{std::move(data)}; + + CORRADE_VERIFY(b.flags() == (PhongMaterialData::Flag::AmbientTexture|PhongMaterialData::Flag::SpecularTexture)); + CORRADE_COMPARE(b.ambientTexture(), 42); + CORRADE_COMPARE(b.diffuseColor(), 0xeebbff_rgbf); + CORRADE_COMPARE(b.specularTexture(), 13); + CORRADE_COMPARE(b.shininess(), 80.0f); + + const int c{}; + PhongMaterialData d{PhongMaterialData::Flag::DiffuseTexture, 100.0f, &c}; + d.ambientColor() = 0xccffbb_rgbf; + d.diffuseTexture() = 42; + d.specularColor() = 0xacabad_rgbf; + d = std::move(b); + + CORRADE_VERIFY(d.flags() == (PhongMaterialData::Flag::AmbientTexture|PhongMaterialData::Flag::SpecularTexture)); + CORRADE_COMPARE(d.ambientTexture(), 42); + CORRADE_COMPARE(d.diffuseColor(), 0xeebbff_rgbf); + CORRADE_COMPARE(d.specularTexture(), 13); + CORRADE_COMPARE(d.shininess(), 80.0f); +} + +void MaterialDataTest::constructMovePhongNoSpecularTexture() { + using namespace Math::Literals; + + const int a{}; + PhongMaterialData data{PhongMaterialData::Flag::AmbientTexture|PhongMaterialData::Flag::DiffuseTexture, 80.0f, &a}; + data.ambientTexture() = 13; + data.diffuseTexture() = 42; + data.specularColor() = 0xacabad_rgbf; + + PhongMaterialData b{std::move(data)}; + + CORRADE_VERIFY(b.flags() == (PhongMaterialData::Flag::AmbientTexture|PhongMaterialData::Flag::DiffuseTexture)); + CORRADE_COMPARE(b.ambientTexture(), 13); + CORRADE_COMPARE(b.diffuseTexture(), 42); + CORRADE_COMPARE(b.specularColor(), 0xacabad_rgbf); + CORRADE_COMPARE(b.shininess(), 80.0f); + + const int c{}; + PhongMaterialData d{PhongMaterialData::Flag::SpecularTexture, 30.0f, &c}; + d.ambientColor() = 0xccffbb_rgbf; + d.diffuseColor() = 0xeebbff_rgbf; + d.specularTexture() = 42; + d = std::move(b); + + CORRADE_VERIFY(d.flags() == (PhongMaterialData::Flag::AmbientTexture|PhongMaterialData::Flag::DiffuseTexture)); + CORRADE_COMPARE(d.ambientTexture(), 13); + CORRADE_COMPARE(d.diffuseTexture(), 42); + CORRADE_COMPARE(d.specularColor(), 0xacabad_rgbf); + CORRADE_COMPARE(d.shininess(), 80.0f); +} + +void MaterialDataTest::debugType() { + std::ostringstream out; + + Debug(&out) << MaterialType::Phong << MaterialType(0xbe); + CORRADE_COMPARE(out.str(), "Trade::MaterialType::Phong Trade::MaterialType(0xbe)\n"); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::MaterialDataTest) diff --git a/src/Magnum/Trade/Test/MeshData2DTest.cpp b/src/Magnum/Trade/Test/MeshData2DTest.cpp new file mode 100644 index 000000000..639891355 --- /dev/null +++ b/src/Magnum/Trade/Test/MeshData2DTest.cpp @@ -0,0 +1,143 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Mesh.h" +#include "Magnum/Math/Vector2.h" +#include "Magnum/Trade/MeshData2D.h" + +namespace Magnum { namespace Trade { namespace Test { + +struct MeshData2DTest: TestSuite::Tester { + explicit MeshData2DTest(); + + void construct(); + void constructNonIndexed(); + void constructNoTexCoords(); + void constructCopy(); + void constructMove(); +}; + +MeshData2DTest::MeshData2DTest() { + addTests({&MeshData2DTest::construct, + &MeshData2DTest::constructNonIndexed, + &MeshData2DTest::constructNoTexCoords, + &MeshData2DTest::constructCopy, + &MeshData2DTest::constructMove}); +} + +void MeshData2DTest::construct() { + const int a{}; + const MeshData2D data{MeshPrimitive::Lines, {12, 1, 0}, + {{{0.5f, 1.0f}, {-1.0f, 0.3f}}, + {{1.4f, 0.2f}, {1.1f, 0.13f}}}, + {{{0.0f, 0.0f}, {0.3f, 0.7f}}, + {{0.1f, 0.2f}, {0.7f, 1.0f}}, + {{0.0f, 0.0f}, {1.0f, 1.0f}}}, + &a}; + + CORRADE_COMPARE(data.primitive(), MeshPrimitive::Lines); + + CORRADE_VERIFY(data.isIndexed()); + CORRADE_COMPARE(data.indices(), (std::vector{12, 1, 0})); + + CORRADE_COMPARE(data.positionArrayCount(), 2); + CORRADE_COMPARE(data.positions(0), (std::vector{{0.5f, 1.0f}, {-1.0f, 0.3f}})); + CORRADE_COMPARE(data.positions(1), (std::vector{{1.4f, 0.2f}, {1.1f, 0.13f}})); + + CORRADE_VERIFY(data.hasTextureCoords2D()); + CORRADE_COMPARE(data.textureCoords2DArrayCount(), 3); + CORRADE_COMPARE(data.textureCoords2D(0), (std::vector{{0.0f, 0.0f}, {0.3f, 0.7f}})); + CORRADE_COMPARE(data.textureCoords2D(1), (std::vector{{0.1f, 0.2f}, {0.7f, 1.0f}})); + CORRADE_COMPARE(data.textureCoords2D(2), (std::vector{{0.0f, 0.0f}, {1.0f, 1.0f}})); + + CORRADE_COMPARE(data.importerState(), &a); +} + +void MeshData2DTest::constructNonIndexed() { + const int a{}; + const MeshData2D data{MeshPrimitive::Lines, {}, + {{{0.5f, 1.0f}, {-1.0f, 0.3f}}}, + {{{0.0f, 0.0f}, {0.3f, 0.7f}}}, + &a}; + + CORRADE_VERIFY(!data.isIndexed()); +} + +void MeshData2DTest::constructNoTexCoords() { + const int a{}; + const MeshData2D data{MeshPrimitive::Lines, {12, 1, 0}, + {{{0.5f, 1.0f}, {-1.0f, 0.3f}}, + {{1.4f, 0.2f}, {1.1f, 0.13f}}}, + {}, + &a}; + + CORRADE_VERIFY(!data.hasTextureCoords2D()); + CORRADE_COMPARE(data.textureCoords2DArrayCount(), 0); +} + +void MeshData2DTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void MeshData2DTest::constructMove() { + const int a{}; + MeshData2D data{MeshPrimitive::LineStrip, {12, 1, 0}, + {{{0.5f, 1.0f}, {-1.0f, 0.3f}}}, + {{{0.0f, 0.0f}, {0.3f, 0.7f}}}, + &a}; + + MeshData2D b{std::move(data)}; + + CORRADE_COMPARE(b.primitive(), MeshPrimitive::LineStrip); + CORRADE_VERIFY(b.isIndexed()); + CORRADE_COMPARE(b.indices(), (std::vector{12, 1, 0})); + CORRADE_COMPARE(b.positionArrayCount(), 1); + CORRADE_COMPARE(b.positions(0), (std::vector{{0.5f, 1.0f}, {-1.0f, 0.3f}})); + CORRADE_COMPARE(b.textureCoords2DArrayCount(), 1); + CORRADE_COMPARE(b.textureCoords2D(0), (std::vector{{0.0f, 0.0f}, {0.3f, 0.7f}})); + CORRADE_COMPARE(b.importerState(), &a); + + const int c{}; + MeshData2D d{MeshPrimitive::TriangleFan, {}, + {{}}, + {}, + &c}; + d = std::move(b); + CORRADE_COMPARE(d.primitive(), MeshPrimitive::LineStrip); + CORRADE_VERIFY(d.isIndexed()); + CORRADE_COMPARE(d.indices(), (std::vector{12, 1, 0})); + CORRADE_COMPARE(d.positionArrayCount(), 1); + CORRADE_COMPARE(d.positions(0), (std::vector{{0.5f, 1.0f}, {-1.0f, 0.3f}})); + CORRADE_COMPARE(d.textureCoords2DArrayCount(), 1); + CORRADE_COMPARE(d.textureCoords2D(0), (std::vector{{0.0f, 0.0f}, {0.3f, 0.7f}})); + CORRADE_COMPARE(d.importerState(), &a); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::MeshData2DTest) diff --git a/src/Magnum/Trade/Test/MeshData3DTest.cpp b/src/Magnum/Trade/Test/MeshData3DTest.cpp new file mode 100644 index 000000000..2ff7e8dce --- /dev/null +++ b/src/Magnum/Trade/Test/MeshData3DTest.cpp @@ -0,0 +1,169 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Mesh.h" +#include "Magnum/Math/Vector3.h" +#include "Magnum/Trade/MeshData3D.h" + +namespace Magnum { namespace Trade { namespace Test { + +struct MeshData3DTest: TestSuite::Tester { + explicit MeshData3DTest(); + + void construct(); + void constructNonIndexed(); + void constructNoNormals(); + void constructNoTexCoords(); + void constructCopy(); + void constructMove(); +}; + +MeshData3DTest::MeshData3DTest() { + addTests({&MeshData3DTest::construct, + &MeshData3DTest::constructNonIndexed, + &MeshData3DTest::constructNoNormals, + &MeshData3DTest::constructNoTexCoords, + &MeshData3DTest::constructCopy, + &MeshData3DTest::constructMove}); +} + +void MeshData3DTest::construct() { + const int a{}; + const MeshData3D data{MeshPrimitive::Lines, {12, 1, 0}, + {{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}}, + {{1.4f, 0.2f, 0.5f}, {1.1f, 0.13f, -0.3f}}}, + {{{0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}}}, + {{{0.0f, 0.0f}, {0.3f, 0.7f}}, + {{0.1f, 0.2f}, {0.7f, 1.0f}}, + {{0.0f, 0.0f}, {1.0f, 1.0f}}}, + &a}; + + CORRADE_COMPARE(data.primitive(), MeshPrimitive::Lines); + + CORRADE_VERIFY(data.isIndexed()); + CORRADE_COMPARE(data.indices(), (std::vector{12, 1, 0})); + + CORRADE_COMPARE(data.positionArrayCount(), 2); + CORRADE_COMPARE(data.positions(0), (std::vector{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}})); + CORRADE_COMPARE(data.positions(1), (std::vector{{1.4f, 0.2f, 0.5f}, {1.1f, 0.13f, -0.3f}})); + + CORRADE_VERIFY(data.hasNormals()); + CORRADE_COMPARE(data.normalArrayCount(), 1); + CORRADE_COMPARE(data.normals(0), (std::vector{{0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}})); + + CORRADE_VERIFY(data.hasTextureCoords2D()); + CORRADE_COMPARE(data.textureCoords2DArrayCount(), 3); + CORRADE_COMPARE(data.textureCoords2D(0), (std::vector{{0.0f, 0.0f}, {0.3f, 0.7f}})); + CORRADE_COMPARE(data.textureCoords2D(1), (std::vector{{0.1f, 0.2f}, {0.7f, 1.0f}})); + CORRADE_COMPARE(data.textureCoords2D(2), (std::vector{{0.0f, 0.0f}, {1.0f, 1.0f}})); + + CORRADE_COMPARE(data.importerState(), &a); +} + +void MeshData3DTest::constructNonIndexed() { + const int a{}; + const MeshData3D data{MeshPrimitive::Lines, {}, + {{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}}}, + {{{0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}}}, + {{{0.0f, 0.0f}, {0.3f, 0.7f}}}, + &a}; + + CORRADE_VERIFY(!data.isIndexed()); +} + +void MeshData3DTest::constructNoNormals() { + const int a{}; + const MeshData3D data{MeshPrimitive::Lines, {12, 1, 0}, + {{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}}}, + {}, + {{{0.0f, 0.0f}, {0.3f, 0.7f}}}, + &a}; + + CORRADE_VERIFY(!data.hasNormals()); + CORRADE_COMPARE(data.normalArrayCount(), 0); +} + +void MeshData3DTest::constructNoTexCoords() { + const int a{}; + const MeshData3D data{MeshPrimitive::Lines, {12, 1, 0}, + {{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}}}, + {{{0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}}}, + {}, + &a}; + + CORRADE_VERIFY(!data.hasTextureCoords2D()); + CORRADE_COMPARE(data.textureCoords2DArrayCount(), 0); +} + +void MeshData3DTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void MeshData3DTest::constructMove() { + const int a{}; + MeshData3D data{MeshPrimitive::LineStrip, {12, 1, 0}, + {{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}}}, + {{{0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}}}, + {{{0.0f, 0.0f}, {0.3f, 0.7f}}}, + &a}; + + MeshData3D b{std::move(data)}; + + CORRADE_COMPARE(b.primitive(), MeshPrimitive::LineStrip); + CORRADE_VERIFY(b.isIndexed()); + CORRADE_COMPARE(b.indices(), (std::vector{12, 1, 0})); + CORRADE_COMPARE(b.positionArrayCount(), 1); + CORRADE_COMPARE(b.positions(0), (std::vector{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}})); + CORRADE_COMPARE(b.normalArrayCount(), 1); + CORRADE_COMPARE(b.normals(0), (std::vector{{0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}})); + CORRADE_COMPARE(b.textureCoords2DArrayCount(), 1); + CORRADE_COMPARE(b.textureCoords2D(0), (std::vector{{0.0f, 0.0f}, {0.3f, 0.7f}})); + CORRADE_COMPARE(b.importerState(), &a); + + const int c{}; + MeshData3D d{MeshPrimitive::TriangleFan, {}, + {{}}, + {}, + {{}}, + &c}; + d = std::move(b); + CORRADE_COMPARE(d.primitive(), MeshPrimitive::LineStrip); + CORRADE_VERIFY(d.isIndexed()); + CORRADE_COMPARE(d.indices(), (std::vector{12, 1, 0})); + CORRADE_COMPARE(d.positionArrayCount(), 1); + CORRADE_COMPARE(d.positions(0), (std::vector{{0.5f, 1.0f, 0.1f}, {-1.0f, 0.3f, -1.0f}})); + CORRADE_COMPARE(d.normalArrayCount(), 1); + CORRADE_COMPARE(d.normals(0), (std::vector{{0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}})); + CORRADE_COMPARE(d.textureCoords2DArrayCount(), 1); + CORRADE_COMPARE(d.textureCoords2D(0), (std::vector{{0.0f, 0.0f}, {0.3f, 0.7f}})); + CORRADE_COMPARE(d.importerState(), &a); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::MeshData3DTest) diff --git a/src/Magnum/Trade/Test/ObjectData2DTest.cpp b/src/Magnum/Trade/Test/ObjectData2DTest.cpp index fa65e8e78..5e65fe5ba 100644 --- a/src/Magnum/Trade/Test/ObjectData2DTest.cpp +++ b/src/Magnum/Trade/Test/ObjectData2DTest.cpp @@ -26,7 +26,7 @@ #include #include -#include "Magnum/Trade/ObjectData2D.h" +#include "Magnum/Trade/MeshObjectData2D.h" namespace Magnum { namespace Trade { namespace Test { @@ -34,17 +34,91 @@ class ObjectData2DTest: public TestSuite::Tester { public: explicit ObjectData2DTest(); - void debug(); + void constructEmpty(); + void constructMesh(); + void constructCamera(); + void constructCopy(); + void constructMoveMesh(); + + void debugType(); }; ObjectData2DTest::ObjectData2DTest() { - addTests({&ObjectData2DTest::debug}); + addTests({&ObjectData2DTest::constructEmpty, + &ObjectData2DTest::constructMesh, + &ObjectData2DTest::constructCamera, + &ObjectData2DTest::constructCopy, + &ObjectData2DTest::constructMoveMesh, + + &ObjectData2DTest::debugType}); +} + +void ObjectData2DTest::constructEmpty() { + const int a{}; + const ObjectData2D data{{0, 2, 3}, Matrix3::translation(Vector2::xAxis(-4.0f)), &a}; + + CORRADE_COMPARE(data.children(), (std::vector{0, 2, 3})); + CORRADE_COMPARE(data.transformation(), Matrix3::translation(Vector2::xAxis(-4.0f))); + CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Empty); + CORRADE_COMPARE(data.instance(), -1); +} + +void ObjectData2DTest::constructMesh() { + const int a{}; + const MeshObjectData2D data{{1, 3}, Matrix3::translation(Vector2::yAxis(5.0f)), 13, 42, &a}; + + CORRADE_COMPARE(data.children(), (std::vector{1, 3})); + CORRADE_COMPARE(data.transformation(), Matrix3::translation(Vector2::yAxis(5.0f))); + CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(data.instance(), 13); + CORRADE_COMPARE(data.material(), 42); +} + +void ObjectData2DTest::constructCamera() { + const int a{}; + const ObjectData2D data{{1, 3}, Matrix3::translation(Vector2::yAxis(5.0f)), ObjectInstanceType2D::Camera, 42, &a}; + + CORRADE_COMPARE(data.children(), (std::vector{1, 3})); + CORRADE_COMPARE(data.transformation(), Matrix3::translation(Vector2::yAxis(5.0f))); + CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Camera); + CORRADE_COMPARE(data.instance(), 42); +} + +void ObjectData2DTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void ObjectData2DTest::constructMoveMesh() { + const int a{}; + MeshObjectData2D data{{1, 3}, Matrix3::translation(Vector2::yAxis(5.0f)), 13, 42, &a}; + + MeshObjectData2D b{std::move(data)}; + + CORRADE_COMPARE(b.children(), (std::vector{1, 3})); + CORRADE_COMPARE(b.transformation(), Matrix3::translation(Vector2::yAxis(5.0f))); + CORRADE_COMPARE(b.instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(b.instance(), 13); + CORRADE_COMPARE(b.material(), 42); + + const int c{}; + MeshObjectData2D d{{0, 1}, {}, 27, -1, &c}; + + d = std::move(b); + + CORRADE_COMPARE(d.children(), (std::vector{1, 3})); + CORRADE_COMPARE(d.transformation(), Matrix3::translation(Vector2::yAxis(5.0f))); + CORRADE_COMPARE(d.instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(d.instance(), 13); + CORRADE_COMPARE(d.material(), 42); } -void ObjectData2DTest::debug() { +void ObjectData2DTest::debugType() { std::ostringstream o; - Debug(&o) << ObjectInstanceType2D::Empty; - CORRADE_COMPARE(o.str(), "Trade::ObjectInstanceType2D::Empty\n"); + Debug(&o) << ObjectInstanceType2D::Empty << ObjectInstanceType2D(0xbe); + CORRADE_COMPARE(o.str(), "Trade::ObjectInstanceType2D::Empty Trade::ObjectInstanceType2D(0xbe)\n"); } }}} diff --git a/src/Magnum/Trade/Test/ObjectData3DTest.cpp b/src/Magnum/Trade/Test/ObjectData3DTest.cpp index 4f5a0d674..bc7d32745 100644 --- a/src/Magnum/Trade/Test/ObjectData3DTest.cpp +++ b/src/Magnum/Trade/Test/ObjectData3DTest.cpp @@ -26,7 +26,7 @@ #include #include -#include "Magnum/Trade/ObjectData3D.h" +#include "Magnum/Trade/MeshObjectData3D.h" namespace Magnum { namespace Trade { namespace Test { @@ -34,17 +34,103 @@ class ObjectData3DTest: public TestSuite::Tester { public: explicit ObjectData3DTest(); - void debug(); + void constructEmpty(); + void constructMesh(); + void constructCamera(); + void constructLight(); + void constructCopy(); + void constructMoveMesh(); + + void debugType(); }; ObjectData3DTest::ObjectData3DTest() { - addTests({&ObjectData3DTest::debug}); + addTests({&ObjectData3DTest::constructEmpty, + &ObjectData3DTest::constructMesh, + &ObjectData3DTest::constructCamera, + &ObjectData3DTest::constructLight, + &ObjectData3DTest::constructCopy, + &ObjectData3DTest::constructMoveMesh, + + &ObjectData3DTest::debugType}); +} + +void ObjectData3DTest::constructEmpty() { + const int a{}; + const ObjectData3D data{{0, 2, 3}, Matrix4::translation(Vector3::xAxis(-4.0f)), &a}; + + CORRADE_COMPARE(data.children(), (std::vector{0, 2, 3})); + CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::xAxis(-4.0f))); + CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Empty); + CORRADE_COMPARE(data.instance(), -1); +} + +void ObjectData3DTest::constructMesh() { + const int a{}; + const MeshObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), 13, 42, &a}; + + CORRADE_COMPARE(data.children(), (std::vector{1, 3})); + CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::yAxis(5.0f))); + CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(data.instance(), 13); + CORRADE_COMPARE(data.material(), 42); +} + +void ObjectData3DTest::constructCamera() { + const int a{}; + const ObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), ObjectInstanceType3D::Camera, 42, &a}; + + CORRADE_COMPARE(data.children(), (std::vector{1, 3})); + CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::yAxis(5.0f))); + CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Camera); + CORRADE_COMPARE(data.instance(), 42); +} + +void ObjectData3DTest::constructLight() { + const int a{}; + const ObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), ObjectInstanceType3D::Light, 42, &a}; + + CORRADE_COMPARE(data.children(), (std::vector{1, 3})); + CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::yAxis(5.0f))); + CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Light); + CORRADE_COMPARE(data.instance(), 42); +} + +void ObjectData3DTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void ObjectData3DTest::constructMoveMesh() { + const int a{}; + MeshObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), 13, 42, &a}; + + MeshObjectData3D b{std::move(data)}; + + CORRADE_COMPARE(b.children(), (std::vector{1, 3})); + CORRADE_COMPARE(b.transformation(), Matrix4::translation(Vector3::yAxis(5.0f))); + CORRADE_COMPARE(b.instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(b.instance(), 13); + CORRADE_COMPARE(b.material(), 42); + + const int c{}; + MeshObjectData3D d{{0, 1}, {}, 27, -1, &c}; + + d = std::move(b); + + CORRADE_COMPARE(d.children(), (std::vector{1, 3})); + CORRADE_COMPARE(d.transformation(), Matrix4::translation(Vector3::yAxis(5.0f))); + CORRADE_COMPARE(d.instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(d.instance(), 13); + CORRADE_COMPARE(d.material(), 42); } -void ObjectData3DTest::debug() { +void ObjectData3DTest::debugType() { std::ostringstream o; - Debug(&o) << ObjectInstanceType3D::Light; - CORRADE_COMPARE(o.str(), "Trade::ObjectInstanceType3D::Light\n"); + Debug(&o) << ObjectInstanceType3D::Light << ObjectInstanceType3D(0xbe); + CORRADE_COMPARE(o.str(), "Trade::ObjectInstanceType3D::Light Trade::ObjectInstanceType3D(0xbe)\n"); } }}} diff --git a/src/Magnum/Trade/Test/SceneDataTest.cpp b/src/Magnum/Trade/Test/SceneDataTest.cpp new file mode 100644 index 000000000..58dcc34ca --- /dev/null +++ b/src/Magnum/Trade/Test/SceneDataTest.cpp @@ -0,0 +1,82 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Trade/SceneData.h" +#include "Magnum/Magnum.h" + +namespace Magnum { namespace Trade { namespace Test { + +struct SceneDataTest: TestSuite::Tester { + explicit SceneDataTest(); + + void construct(); + void constructCopy(); + void constructMove(); +}; + +SceneDataTest::SceneDataTest() { + addTests({&SceneDataTest::construct, + &SceneDataTest::constructCopy, + &SceneDataTest::constructMove}); +} + +void SceneDataTest::construct() { + const int a{}; + const SceneData data{{0, 1, 4}, {2, 5}, &a}; + + CORRADE_COMPARE(data.children2D(), (std::vector{0, 1, 4})); + CORRADE_COMPARE(data.children3D(), (std::vector{2, 5})); + CORRADE_COMPARE(data.importerState(), &a); +} + +void SceneDataTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void SceneDataTest::constructMove() { + const int a{}; + SceneData data{{0, 1, 4}, {2, 5}, &a}; + + SceneData b{std::move(data)}; + + CORRADE_COMPARE(b.children2D(), (std::vector{0, 1, 4})); + CORRADE_COMPARE(b.children3D(), (std::vector{2, 5})); + CORRADE_COMPARE(b.importerState(), &a); + + const int c{}; + SceneData d{{1, 3}, {1, 4, 5}, &c}; + d = std::move(b); + + CORRADE_COMPARE(d.children2D(), (std::vector{0, 1, 4})); + CORRADE_COMPARE(d.children3D(), (std::vector{2, 5})); + CORRADE_COMPARE(d.importerState(), &a); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::SceneDataTest) diff --git a/src/Magnum/Trade/Test/TextureDataTest.cpp b/src/Magnum/Trade/Test/TextureDataTest.cpp index 30c0050c1..ed8963ad2 100644 --- a/src/Magnum/Trade/Test/TextureDataTest.cpp +++ b/src/Magnum/Trade/Test/TextureDataTest.cpp @@ -34,18 +34,89 @@ class TextureDataTest: public TestSuite::Tester { public: explicit TextureDataTest(); - void debug(); + void construct(); + void constructCopy(); + void constructMove(); + + void debugType(); }; TextureDataTest::TextureDataTest() { - addTests({&TextureDataTest::debug}); + addTests({&TextureDataTest::construct, + &TextureDataTest::constructCopy, + &TextureDataTest::constructMove, + + &TextureDataTest::debugType}); +} + +void TextureDataTest::construct() { + const int a{}; + const TextureData data{TextureData::Type::Cube, + Sampler::Filter::Linear, + Sampler::Filter::Nearest, + Sampler::Mipmap::Nearest, + {Sampler::Wrapping::Repeat, Sampler::Wrapping::ClampToEdge, Sampler::Wrapping::MirroredRepeat}, + 42, + &a}; + + CORRADE_COMPARE(data.type(), TextureData::Type::Cube); + CORRADE_COMPARE(data.minificationFilter(), Sampler::Filter::Linear); + CORRADE_COMPARE(data.magnificationFilter(), Sampler::Filter::Nearest); + CORRADE_COMPARE(data.mipmapFilter(), Sampler::Mipmap::Nearest); + CORRADE_COMPARE(data.wrapping(), (Array3D{Sampler::Wrapping::Repeat, Sampler::Wrapping::ClampToEdge, Sampler::Wrapping::MirroredRepeat})); + CORRADE_COMPARE(data.image(), 42); + CORRADE_COMPARE(data.importerState(), &a); +} + +void TextureDataTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void TextureDataTest::constructMove() { + const int a{}; + TextureData data{TextureData::Type::Cube, + Sampler::Filter::Linear, + Sampler::Filter::Nearest, + Sampler::Mipmap::Nearest, + {Sampler::Wrapping::Repeat, Sampler::Wrapping::ClampToEdge, Sampler::Wrapping::MirroredRepeat}, + 42, + &a}; + + TextureData b{std::move(data)}; + + CORRADE_COMPARE(b.type(), TextureData::Type::Cube); + CORRADE_COMPARE(b.minificationFilter(), Sampler::Filter::Linear); + CORRADE_COMPARE(b.magnificationFilter(), Sampler::Filter::Nearest); + CORRADE_COMPARE(b.mipmapFilter(), Sampler::Mipmap::Nearest); + CORRADE_COMPARE(b.wrapping(), (Array3D{Sampler::Wrapping::Repeat, Sampler::Wrapping::ClampToEdge, Sampler::Wrapping::MirroredRepeat})); + CORRADE_COMPARE(b.image(), 42); + CORRADE_COMPARE(b.importerState(), &a); + + const int c{}; + TextureData d{TextureData::Type::Texture2D, + Sampler::Filter::Nearest, + Sampler::Filter::Linear, + Sampler::Mipmap::Base, + Sampler::Wrapping::ClampToEdge, + 13, + &c}; + d = std::move(b); + + CORRADE_COMPARE(d.type(), TextureData::Type::Cube); + CORRADE_COMPARE(d.minificationFilter(), Sampler::Filter::Linear); + CORRADE_COMPARE(d.magnificationFilter(), Sampler::Filter::Nearest); + CORRADE_COMPARE(d.mipmapFilter(), Sampler::Mipmap::Nearest); + CORRADE_COMPARE(d.wrapping(), (Array3D{Sampler::Wrapping::Repeat, Sampler::Wrapping::ClampToEdge, Sampler::Wrapping::MirroredRepeat})); + CORRADE_COMPARE(d.image(), 42); + CORRADE_COMPARE(d.importerState(), &a); } -void TextureDataTest::debug() { +void TextureDataTest::debugType() { std::ostringstream out; - Debug(&out) << TextureData::Type::Texture3D; - CORRADE_COMPARE(out.str(), "Trade::TextureData::Type::Texture3D\n"); + Debug(&out) << TextureData::Type::Texture3D << TextureData::Type(0xbe); + CORRADE_COMPARE(out.str(), "Trade::TextureData::Type::Texture3D Trade::TextureData::Type(0xbe)\n"); } }}} diff --git a/src/Magnum/Trade/Test/configure.h.cmake b/src/Magnum/Trade/Test/configure.h.cmake index d39dc3cdf..017811a26 100644 --- a/src/Magnum/Trade/Test/configure.h.cmake +++ b/src/Magnum/Trade/Test/configure.h.cmake @@ -23,5 +23,5 @@ DEALINGS IN THE SOFTWARE. */ -#define TRADE_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" -#define TRADE_TEST_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}" +#define TRADE_TEST_DIR "${TRADE_TEST_DIR}" +#define TRADE_TEST_OUTPUT_DIR "${TRADE_TEST_OUTPUT_DIR}" diff --git a/src/Magnum/Trade/TextureData.cpp b/src/Magnum/Trade/TextureData.cpp index d0be1a163..e1d4fcb2d 100644 --- a/src/Magnum/Trade/TextureData.cpp +++ b/src/Magnum/Trade/TextureData.cpp @@ -30,15 +30,17 @@ namespace Magnum { namespace Trade { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const TextureData::Type value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value) case TextureData::Type::value: return debug << "Trade::TextureData::Type::" #value; _c(Texture1D) _c(Texture2D) _c(Texture3D) _c(Cube) #undef _c + /* LCOV_EXCL_STOP */ } - return debug << "Trade::TextureData::Type::(unknown)"; + return debug << "Trade::TextureData::Type(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } #endif diff --git a/src/Magnum/Trade/TextureData.h b/src/Magnum/Trade/TextureData.h index 23cfe3071..b942959b3 100644 --- a/src/Magnum/Trade/TextureData.h +++ b/src/Magnum/Trade/TextureData.h @@ -62,19 +62,19 @@ class TextureData { * @param image Texture image ID * @param importerState Importer-specific state */ - TextureData(Type type, Sampler::Filter minificationFilter, Sampler::Filter magnificationFilter, Sampler::Mipmap mipmapFilter, Array3D wrapping, UnsignedInt image, const void* importerState = nullptr): _type{type}, _minificationFilter{minificationFilter}, _magnificationFilter{magnificationFilter}, _mipmapFilter{mipmapFilter}, _wrapping{wrapping}, _image{image}, _importerState{importerState} {} + TextureData(Type type, Sampler::Filter minificationFilter, Sampler::Filter magnificationFilter, Sampler::Mipmap mipmapFilter, Array3D wrapping, UnsignedInt image, const void* importerState = nullptr) noexcept: _type{type}, _minificationFilter{minificationFilter}, _magnificationFilter{magnificationFilter}, _mipmapFilter{mipmapFilter}, _wrapping{wrapping}, _image{image}, _importerState{importerState} {} /** @brief Copying is not allowed */ TextureData(const TextureData&) = delete; /** @brief Move constructor */ - TextureData(TextureData&&) = default; + TextureData(TextureData&&) noexcept = default; /** @brief Copying is not allowed */ TextureData& operator=(const TextureData&) = delete; /** @brief Move assignment */ - TextureData& operator=(TextureData&&) = default; + TextureData& operator=(TextureData&&) noexcept = default; /** @brief Texture type */ Type type() const { return _type; } diff --git a/src/Magnum/Trade/imageconverter.cpp b/src/Magnum/Trade/imageconverter.cpp new file mode 100644 index 000000000..9821ddcac --- /dev/null +++ b/src/Magnum/Trade/imageconverter.cpp @@ -0,0 +1,107 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include + +#include "Magnum/PixelFormat.h" +#include "Magnum/Trade/AbstractImporter.h" +#include "Magnum/Trade/AbstractImageConverter.h" +#include "Magnum/Trade/ImageData.h" + +#include "imageconverterConfigure.h" + +namespace Magnum { + +/** +@page magnum-imageconverter Image conversion utility +@brief Converts images of different formats + +@section magnum-imageconverter-usage Usage + + magnum-imageconverter [-h|--help] [--importer IMPORTER] [--converter CONVERTER] [--plugin-dir DIR] [--] input output + +Arguments: + +- `input` -- input image +- `output` -- output image +- `-h`, `--help` -- display this help message and exit +- `--importer IMPORTER` -- image importer plugin (default: + @ref Trade::AnyImageImporter "AnyImageImporter") +- `--converter CONVERTER` -- image converter plugin (default: + @ref Trade::AnyImageConverter "AnyImageConverter") +- `--plugin-dir DIR` -- base plugin dir (defaults to plugin directory in + Magnum install location) + +@section magnum-imageconverter-example Example usage + +Converting a JPEG file to a PNG: + + magnum-imageconverter image.jpg image.png + +*/ + +} + +using namespace Magnum; + +int main(int argc, char** argv) { + Utility::Arguments args; + args.addArgument("input").setHelp("input", "input image") + .addArgument("output").setHelp("output", "output image") + .addOption("importer", "AnyImageImporter").setHelp("importer", "image importer plugin") + .addOption("converter", "AnyImageConverter").setHelp("converter", "image converter plugin") + .addOption("plugin-dir", Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), MAGNUM_PLUGINS_DIR)).setHelp("plugin-dir", "base plugin dir", "DIR") + .setHelp("Converts images of different formats.") + .parse(argc, argv); + + /* Load importer plugin */ + PluginManager::Manager importerManager(Utility::Directory::join(args.value("plugin-dir"), "importers/")); + if(!(importerManager.load(args.value("importer")) & PluginManager::LoadState::Loaded)) + return 1; + std::unique_ptr importer = importerManager.instance(args.value("importer")); + + /* Load converter plugin */ + PluginManager::Manager converterManager(Utility::Directory::join(args.value("plugin-dir"), "imageconverters/")); + if(!(converterManager.load(args.value("converter")) & PluginManager::LoadState::Loaded)) + return 1; + std::unique_ptr converter = converterManager.instance(args.value("converter")); + + /* Open input file */ + std::optional image; + if(!importer->openFile(args.value("input")) || !(image = importer->image2D(0))) { + Error() << "Cannot open file" << args.value("input"); + return 1; + } + + Debug() << "Converting image of size" << image->size() << Debug::nospace << ", format" << image->format() << "and type" << image->type() << "to" << args.value("output"); + + /* Save output file */ + if(!converter->exportToFile(*image, args.value("output"))) { + Error() << "Cannot save file" << args.value("output"); + return 1; + } +} diff --git a/src/Magnum/Trade/imageconverterConfigure.h.cmake b/src/Magnum/Trade/imageconverterConfigure.h.cmake new file mode 100644 index 000000000..7411d07a9 --- /dev/null +++ b/src/Magnum/Trade/imageconverterConfigure.h.cmake @@ -0,0 +1,30 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifdef CORRADE_IS_DEBUG_BUILD +#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DEBUG_DIR}" +#else +#define MAGNUM_PLUGINS_DIR "${MAGNUM_PLUGINS_DIR}" +#endif diff --git a/src/Magnum/TransformFeedback.cpp b/src/Magnum/TransformFeedback.cpp index 1ec6160c0..89546dd50 100644 --- a/src/Magnum/TransformFeedback.cpp +++ b/src/Magnum/TransformFeedback.cpp @@ -94,6 +94,18 @@ Int TransformFeedback::maxBuffers() { return value; } + +Int TransformFeedback::maxVertexStreams() { + if(!Context::current().isExtensionSupported()) + return 1; + + GLint& value = Context::current().state().transformFeedback->maxVertexStreams; + + if(value == 0) + glGetIntegerv(GL_MAX_VERTEX_STREAMS, &value); + + return value; +} #endif TransformFeedback::TransformFeedback(): _flags{ObjectFlag::DeleteOnDestruction} { diff --git a/src/Magnum/TransformFeedback.h b/src/Magnum/TransformFeedback.h index 602d3ba2a..3e3fa5cd2 100644 --- a/src/Magnum/TransformFeedback.h +++ b/src/Magnum/TransformFeedback.h @@ -147,6 +147,18 @@ class MAGNUM_EXPORT TransformFeedback: public AbstractObject { * WebGL. */ static Int maxBuffers(); + + /** + * @brief Max supported vertex stream count + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If extension @extension{ARB,transform_feedback3} (part + * of OpenGL 4.0) is not available, returns `1`. + * @see @fn_gl{Get} with @def_gl{MAX_VERTEX_STREAMS} + * @requires_gl Multiple vertex streams are not available in OpenGL ES + * and WebGL. + */ + static Int maxVertexStreams(); #endif /** diff --git a/src/Magnum/Types.h b/src/Magnum/Types.h index 0b73e006e..228137ccd 100644 --- a/src/Magnum/Types.h +++ b/src/Magnum/Types.h @@ -48,9 +48,7 @@ typedef std::int64_t Long; #endif typedef float Float; -#ifndef MAGNUM_TARGET_GLES typedef double Double; -#endif } diff --git a/src/Magnum/Version.cpp b/src/Magnum/Version.cpp index c0853dff7..43c42aa51 100644 --- a/src/Magnum/Version.cpp +++ b/src/Magnum/Version.cpp @@ -32,6 +32,7 @@ namespace Magnum { #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, Version value) { switch(value) { + /* LCOV_EXCL_START */ #define _c(value, string) case Version::value: return debug << string; _c(None, "None") #ifndef MAGNUM_TARGET_GLES @@ -56,6 +57,7 @@ Debug& operator<<(Debug& debug, Version value) { _c(GLES310, "OpenGL ES 3.1") #endif #undef _c + /* LCOV_EXCL_STOP */ } return debug << "Invalid"; diff --git a/src/Magnum/configure.h.cmake b/src/Magnum/configure.h.cmake index 54abfa21d..7b6751ded 100644 --- a/src/Magnum/configure.h.cmake +++ b/src/Magnum/configure.h.cmake @@ -1,3 +1,5 @@ +#ifndef Magnum_configure_h +#define Magnum_configure_h /* This file is part of Magnum. @@ -25,9 +27,12 @@ #cmakedefine MAGNUM_BUILD_DEPRECATED #cmakedefine MAGNUM_BUILD_STATIC +#cmakedefine MAGNUM_BUILD_MULTITHREADED #cmakedefine MAGNUM_TARGET_GLES #cmakedefine MAGNUM_TARGET_GLES2 #cmakedefine MAGNUM_TARGET_GLES3 #cmakedefine MAGNUM_TARGET_DESKTOP_GLES #cmakedefine MAGNUM_TARGET_WEBGL #cmakedefine MAGNUM_TARGET_HEADLESS + +#endif diff --git a/src/MagnumExternal/OpenAL/extensions.h b/src/MagnumExternal/OpenAL/extensions.h index c0c60c30a..5beb8bb39 100644 --- a/src/MagnumExternal/OpenAL/extensions.h +++ b/src/MagnumExternal/OpenAL/extensions.h @@ -33,6 +33,11 @@ extern "C" { #endif +/* For compatibility with Emscripten that does not define this macro */ +#ifndef AL_APIENTRY +#define AL_APIENTRY +#endif + /* AL_EXT_float32 */ #ifndef AL_EXT_float32 #define AL_EXT_float32 1 @@ -47,6 +52,40 @@ extern "C" { #define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013 #endif +/* AL_EXT_MULAW */ +#ifndef AL_EXT_MULAW +#define AL_EXT_MULAW 1 +#define AL_FORMAT_MONO_MULAW_EXT 0x10014 +#define AL_FORMAT_STEREO_MULAW_EXT 0x10015 +#endif + +/* AL_EXT_ALAW */ +#ifndef AL_EXT_ALAW +#define AL_EXT_ALAW 1 +#define AL_FORMAT_MONO_ALAW_EXT 0x10016 +#define AL_FORMAT_STEREO_ALAW_EXT 0x10017 +#endif + +/* AL_EXT_MCFORMATS */ +#ifndef AL_EXT_MCFORMATS +#define AL_EXT_MCFORMATS 1 +#define AL_FORMAT_QUAD8 0x1204 +#define AL_FORMAT_QUAD16 0x1205 +#define AL_FORMAT_QUAD32 0x1206 +#define AL_FORMAT_REAR8 0x1207 +#define AL_FORMAT_REAR16 0x1208 +#define AL_FORMAT_REAR32 0x1209 +#define AL_FORMAT_51CHN8 0x120A +#define AL_FORMAT_51CHN16 0x120B +#define AL_FORMAT_51CHN32 0x120C +#define AL_FORMAT_61CHN8 0x120D +#define AL_FORMAT_61CHN16 0x120E +#define AL_FORMAT_61CHN32 0x120F +#define AL_FORMAT_71CHN8 0x1210 +#define AL_FORMAT_71CHN16 0x1211 +#define AL_FORMAT_71CHN32 0x1212 +#endif + /* ALC_SOFTX_HRTF */ #ifndef ALC_SOFTX_HRTF #define ALC_SOFTX_HRTF 1 diff --git a/src/MagnumExternal/OpenGL/GL/README.md b/src/MagnumExternal/OpenGL/GL/README.md index 3e57e6550..c879d6f83 100644 --- a/src/MagnumExternal/OpenGL/GL/README.md +++ b/src/MagnumExternal/OpenGL/GL/README.md @@ -1,8 +1,9 @@ OpenGL header and extension loader is generated using flextGL, get it at -[](https://github.com/ginkgo/flextGL). +https://github.com/ginkgo/flextGL. -See [](extensions.txt) for requested version and a list of non-core extensions. -Call `flextGLgen.py` in this directory with the following arguments: +See [extensions.txt](extensions.txt) for requested version and a list of +non-core extensions. Call `flextGLgen.py` in this directory with the following +arguments: .../flextGLgen.py -D . -t . extensions.txt diff --git a/src/MagnumExternal/OpenGL/GLES2/CMakeLists.txt b/src/MagnumExternal/OpenGL/GLES2/CMakeLists.txt index 56d3cb0fd..91ae146a8 100644 --- a/src/MagnumExternal/OpenGL/GLES2/CMakeLists.txt +++ b/src/MagnumExternal/OpenGL/GLES2/CMakeLists.txt @@ -23,10 +23,29 @@ # DEALINGS IN THE SOFTWARE. # +# Desktop GLES on Windows still links to opengl32.dll so we have a special +# function loading code that queries everything above OpenGL 1.1 +if(CORRADE_TARGET_WINDOWS AND MAGNUM_TARGET_DESKTOP_GLES) + set(MagnumOpenGL_HEADERS flextGLWindowsDesktop.h) + set(MagnumOpenGL_SRCS flextGLWindowsDesktop.cpp) + +# NaCl and Emscripten are special, provide only some extensions for them (and +# no extension loading) +elseif(CORRADE_TARGET_NACL) + set(MagnumOpenGL_HEADERS flextGLNaCl.h) +elseif(CORRADE_TARGET_EMSCRIPTEN) + set(MagnumOpenGL_HEADERS flextGLEmscripten.h) + +# The common sane case +else() + set(MagnumOpenGL_HEADERS flextGL.h) + set(MagnumOpenGL_SRCS flextGL.cpp) +endif() + # NaCl and Emscripten don't have the ability to load function pointers manually if(NOT CORRADE_TARGET_NACL AND NOT CORRADE_TARGET_EMSCRIPTEN) - # flextGLPlatform.cpp is compiled as part of Magnum*Context libraries in Platform - add_library(MagnumFlextGLObjects OBJECT flextGL.cpp) + # flextGLPlatform*.cpp is compiled as part of Magnum*Context libraries in Platform + add_library(MagnumFlextGLObjects OBJECT ${MagnumOpenGL_SRCS}) target_include_directories(MagnumFlextGLObjects PUBLIC $) if(NOT BUILD_STATIC) @@ -37,13 +56,4 @@ if(NOT CORRADE_TARGET_NACL AND NOT CORRADE_TARGET_EMSCRIPTEN) endif() endif() -# NaCl and Emscripten are special, provide only some extensions for them -if(CORRADE_TARGET_NACL) - set(MagnumOpenGL_HEADERS flextGLNaCl.h) -elseif(CORRADE_TARGET_EMSCRIPTEN) - set(MagnumOpenGL_HEADERS flextGLEmscripten.h) -else() - set(MagnumOpenGL_HEADERS flextGL.h) -endif() - install(FILES ${MagnumOpenGL_HEADERS} DESTINATION ${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR}/OpenGL/GLES2) diff --git a/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt b/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt index 8a4eb5925..b1a229f11 100644 --- a/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt +++ b/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt @@ -13,6 +13,7 @@ extension OES_texture_half_float optional extension OES_texture_float optional extension OES_standard_derivatives optional extension OES_vertex_array_object optional +extension OES_fbo_render_mipmap optional # These are used as a base for WEBGL_* extensions extension ANGLE_depth_texture optional extension EXT_draw_buffers optional diff --git a/src/MagnumExternal/OpenGL/GLES2/README.md b/src/MagnumExternal/OpenGL/GLES2/README.md index b4f73b127..4ea572a1b 100644 --- a/src/MagnumExternal/OpenGL/GLES2/README.md +++ b/src/MagnumExternal/OpenGL/GLES2/README.md @@ -1,14 +1,24 @@ OpenGL header and extension loader is generated using flextGL, get it at https://github.com/ginkgo/flextGL. -See [extensions.txt](extensions.txt) for requested version and a list of non-core extensions. -Call `flextGLgen.py` in this directory with the following arguments to generate -files for generic GLES2 implementations: +See [extensions.txt](extensions.txt) for requested version and a list of +non-core extensions. Call `flextGLgen.py` in this directory with the following +arguments to generate files for generic GLES2 implementations: .../flextGLgen.py -D . -t . extensions.txt -It will generate `flextGL.h`, `flextGL.cpp`, `flextGLPlatform.cpp` and -`flextGLPlatformIOS.cpp` files. +It will generate `flextGL.h`, `flextGL.cpp`, `flextGLPlatform.cpp`, +`flextGLWindowsDesktop.h`, `flextGLWindowsDesktop.cpp`, +`flextGLPlatformWindowsDesktop.cpp` and `flextGLPlatformIOS.cpp` files. + +Desktop GLES on Windows still links to the ancient `opengl32.dll` which exports +only OpenGL 1.1 symbols, so we have a special set of headers that queries +pointers for everything above OpenGL 1.1 (instead of everything above OpenGL ES +2.0). + +iOS, on the other hand, doesn't have any extension loader mechanism and all +supported entrypoints are exported from the library, so we set the function +pointers to those exported symbols in case the system GL header defines them. NaCl and Emscripten don't have the ability to manually load extension pointers, thus they have only header files: diff --git a/src/MagnumExternal/OpenGL/GLES2/extensions.txt b/src/MagnumExternal/OpenGL/GLES2/extensions.txt index 9abbd3b66..9c290dfcd 100644 --- a/src/MagnumExternal/OpenGL/GLES2/extensions.txt +++ b/src/MagnumExternal/OpenGL/GLES2/extensions.txt @@ -35,6 +35,7 @@ extension NV_shadow_samplers_array optional extension NV_shadow_samplers_cube optional extension OES_depth24 optional extension OES_element_index_uint optional +extension OES_fbo_render_mipmap optional extension OES_rgb8_rgba8 optional extension OES_texture_3D optional extension OES_texture_half_float_linear optional @@ -89,3 +90,39 @@ extension OES_mapbuffer optional extension OES_stencil1 optional extension OES_stencil4 optional extension OES_texture_stencil8 optional + +begin functions blacklist + # These are listed in EXT_separate_shader_objects with only the comment + # saying "Depends on OpenGL ES 3.0 or GL_NV_non_square_matrices". No way to + # parse that so I have to disable them manually. iOS extension header + # doesn't provide these for GLES2. + ProgramUniform1uiEXT + ProgramUniform2uiEXT + ProgramUniform3uiEXT + ProgramUniform4uiEXT + ProgramUniform1uivEXT + ProgramUniform2uivEXT + ProgramUniform3uivEXT + ProgramUniform4uivEXT + ProgramUniformMatrix2x3fvEXT + ProgramUniformMatrix3x2fvEXT + ProgramUniformMatrix2x4fvEXT + ProgramUniformMatrix4x2fvEXT + ProgramUniformMatrix3x4fvEXT + ProgramUniformMatrix4x3fvEXT + + # These are listed in EXT_texture_storage with a comment saying "Not clear + # all of these enums should be here for OpenGL ES. Many are only defined if + # other extensions also requiring them are supported". iOS extension header + # doesn't provide this one and TexStorage3DEXT, however I need the 3D for + # OES_texture_3D so I'm having an ugly workaround in flextGLPlatformIOS.cpp. + TexStorage1DEXT + + # These are listed in EXT_texture_storage with a comment saying "Supported + # only if GL_EXT_direct_state_access is supported". Again impossible to + # parse so I have to disable them manually. iOS extension header doesn't + # provide these for GLES2. + TextureStorage1DEXT + TextureStorage2DEXT + TextureStorage3DEXT +end functions blacklist diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGL.cpp b/src/MagnumExternal/OpenGL/GLES2/flextGL.cpp index de1caad84..a0d0f33d8 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGL.cpp +++ b/src/MagnumExternal/OpenGL/GLES2/flextGL.cpp @@ -96,35 +96,21 @@ FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fEXT)(GLuint, GLint, GLfloat FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iEXT)(GLuint, GLint, GLint) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uiEXT)(GLuint, GLint, GLuint) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fEXT)(GLuint, GLint, GLfloat, GLfloat) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iEXT)(GLuint, GLint, GLint, GLint) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uiEXT)(GLuint, GLint, GLuint, GLuint) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iEXT)(GLuint, GLint, GLint, GLint, GLint) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iEXT)(GLuint, GLint, GLint, GLint, GLint, GLint) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStagesEXT)(GLuint, GLbitfield, GLuint) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipelineEXT)(GLuint) = nullptr; @@ -139,12 +125,8 @@ FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIivEXT)(GLenum, GLenum, const G FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIuivEXT)(GLenum, GLenum, const GLuint *) = nullptr; /* GL_EXT_texture_storage */ -FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage1DEXT)(GLenum, GLsizei, GLenum, GLsizei) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglTextureStorage1DEXT)(GLuint, GLenum, GLsizei, GLenum, GLsizei) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglTextureStorage2DEXT)(GLuint, GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; -FLEXTGL_EXPORT void(APIENTRY *flextglTextureStorage3DEXT)(GLuint, GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei) = nullptr; /* GL_KHR_blend_equation_advanced */ FLEXTGL_EXPORT void(APIENTRY *flextglBlendBarrierKHR)(void) = nullptr; diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGL.h b/src/MagnumExternal/OpenGL/GLES2/flextGL.h index 606c85332..aaefc5153 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGL.h +++ b/src/MagnumExternal/OpenGL/GLES2/flextGL.h @@ -1347,10 +1347,6 @@ GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iEXT)(GLuint, GLint, G #define glProgramUniform1iEXT flextglProgramUniform1iEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ivEXT)(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform1ivEXT flextglProgramUniform1ivEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uiEXT)(GLuint, GLint, GLuint); -#define glProgramUniform1uiEXT flextglProgramUniform1uiEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uivEXT)(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform1uivEXT flextglProgramUniform1uivEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fEXT)(GLuint, GLint, GLfloat, GLfloat); #define glProgramUniform2fEXT flextglProgramUniform2fEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); @@ -1359,10 +1355,6 @@ GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iEXT)(GLuint, GLint, G #define glProgramUniform2iEXT flextglProgramUniform2iEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ivEXT)(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform2ivEXT flextglProgramUniform2ivEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uiEXT)(GLuint, GLint, GLuint, GLuint); -#define glProgramUniform2uiEXT flextglProgramUniform2uiEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uivEXT)(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform2uivEXT flextglProgramUniform2uivEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat); #define glProgramUniform3fEXT flextglProgramUniform3fEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); @@ -1371,10 +1363,6 @@ GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iEXT)(GLuint, GLint, G #define glProgramUniform3iEXT flextglProgramUniform3iEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ivEXT)(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform3ivEXT flextglProgramUniform3ivEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint); -#define glProgramUniform3uiEXT flextglProgramUniform3uiEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uivEXT)(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform3uivEXT flextglProgramUniform3uivEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat); #define glProgramUniform4fEXT flextglProgramUniform4fEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); @@ -1383,28 +1371,12 @@ GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iEXT)(GLuint, GLint, G #define glProgramUniform4iEXT flextglProgramUniform4iEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ivEXT)(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform4ivEXT flextglProgramUniform4ivEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint); -#define glProgramUniform4uiEXT flextglProgramUniform4uiEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uivEXT)(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform4uivEXT flextglProgramUniform4uivEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); #define glProgramUniformMatrix2fvEXT flextglProgramUniformMatrix2fvEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix2x3fvEXT flextglProgramUniformMatrix2x3fvEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix2x4fvEXT flextglProgramUniformMatrix2x4fvEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); #define glProgramUniformMatrix3fvEXT flextglProgramUniformMatrix3fvEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix3x2fvEXT flextglProgramUniformMatrix3x2fvEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix3x4fvEXT flextglProgramUniformMatrix3x4fvEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); #define glProgramUniformMatrix4fvEXT flextglProgramUniformMatrix4fvEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix4x2fvEXT flextglProgramUniformMatrix4x2fvEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix4x3fvEXT flextglProgramUniformMatrix4x3fvEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStagesEXT)(GLuint, GLbitfield, GLuint); #define glUseProgramStagesEXT flextglUseProgramStagesEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipelineEXT)(GLuint); @@ -1431,18 +1403,10 @@ GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIuivEXT)(GLenum, GLenum, /* GL_EXT_texture_storage */ -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage1DEXT)(GLenum, GLsizei, GLenum, GLsizei); -#define glTexStorage1DEXT flextglTexStorage1DEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); #define glTexStorage2DEXT flextglTexStorage2DEXT GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei); #define glTexStorage3DEXT flextglTexStorage3DEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTextureStorage1DEXT)(GLuint, GLenum, GLsizei, GLenum, GLsizei); -#define glTextureStorage1DEXT flextglTextureStorage1DEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTextureStorage2DEXT)(GLuint, GLenum, GLsizei, GLenum, GLsizei, GLsizei); -#define glTextureStorage2DEXT flextglTextureStorage2DEXT -GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTextureStorage3DEXT)(GLuint, GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei); -#define glTextureStorage3DEXT flextglTextureStorage3DEXT /* GL_KHR_blend_equation_advanced */ diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLNaCl.h b/src/MagnumExternal/OpenGL/GLES2/flextGLNaCl.h index d711c9d21..abae35d93 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGLNaCl.h +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLNaCl.h @@ -695,6 +695,11 @@ typedef khronos_ssize_t GLsizeiptr; #define GL_BGRA_EXT 0x80E1 #define GL_BGRA8_EXT 0x93A1 +/* GL_ARM_shader_framebuffer_fetch */ + +#define GL_FETCH_PER_SAMPLE_ARM 0x8F65 +#define GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66 + /* GL_EXT_texture_filter_anisotropic */ #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE @@ -721,6 +726,10 @@ typedef khronos_ssize_t GLsizeiptr; #define GL_SAMPLER 0x82E6 #define GL_TRANSFORM_FEEDBACK 0x8E22 +/* GL_EXT_shader_framebuffer_fetch */ + +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 + /* GL_EXT_disjoint_timer_query */ #define GL_QUERY_COUNTER_BITS_EXT 0x8864 @@ -956,6 +965,10 @@ typedef khronos_ssize_t GLsizeiptr; #define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC #define GL_NONE 0 +/* GL_KHR_no_error */ + +#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008 + /* GL_NV_texture_border_clamp */ #define GL_TEXTURE_BORDER_COLOR_NV 0x1004 @@ -1050,6 +1063,16 @@ GL_APICALL void GL_APIENTRY GLES2ResolveMultisampleFramebufferAPPLE(void); #define GL_ARM_rgba8 1 #endif +/* GL_ARM_shader_framebuffer_fetch */ +#ifndef GL_ARM_shader_framebuffer_fetch +#define GL_ARM_shader_framebuffer_fetch 1 +#endif + +/* GL_ARM_shader_framebuffer_fetch_depth_stencil */ +#ifndef GL_ARM_shader_framebuffer_fetch_depth_stencil +#define GL_ARM_shader_framebuffer_fetch_depth_stencil 1 +#endif + /* GL_ES_VERSION_2_0 */ #ifndef GL_ES_VERSION_2_0 #define GL_ES_VERSION_2_0 1 @@ -1531,10 +1554,6 @@ GL_APICALL void GL_APIENTRY GLES2ProgramUniform1iEXT(GLuint, GLint, GLint); #define glProgramUniform1iEXT GLES2ProgramUniform1iEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform1ivEXT(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform1ivEXT GLES2ProgramUniform1ivEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform1uiEXT(GLuint, GLint, GLuint); -#define glProgramUniform1uiEXT GLES2ProgramUniform1uiEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform1uivEXT(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform1uivEXT GLES2ProgramUniform1uivEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform2fEXT(GLuint, GLint, GLfloat, GLfloat); #define glProgramUniform2fEXT GLES2ProgramUniform2fEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform2fvEXT(GLuint, GLint, GLsizei, const GLfloat *); @@ -1543,10 +1562,6 @@ GL_APICALL void GL_APIENTRY GLES2ProgramUniform2iEXT(GLuint, GLint, GLint, GLint #define glProgramUniform2iEXT GLES2ProgramUniform2iEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform2ivEXT(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform2ivEXT GLES2ProgramUniform2ivEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform2uiEXT(GLuint, GLint, GLuint, GLuint); -#define glProgramUniform2uiEXT GLES2ProgramUniform2uiEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform2uivEXT(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform2uivEXT GLES2ProgramUniform2uivEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform3fEXT(GLuint, GLint, GLfloat, GLfloat, GLfloat); #define glProgramUniform3fEXT GLES2ProgramUniform3fEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform3fvEXT(GLuint, GLint, GLsizei, const GLfloat *); @@ -1555,10 +1570,6 @@ GL_APICALL void GL_APIENTRY GLES2ProgramUniform3iEXT(GLuint, GLint, GLint, GLint #define glProgramUniform3iEXT GLES2ProgramUniform3iEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform3ivEXT(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform3ivEXT GLES2ProgramUniform3ivEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform3uiEXT(GLuint, GLint, GLuint, GLuint, GLuint); -#define glProgramUniform3uiEXT GLES2ProgramUniform3uiEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform3uivEXT(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform3uivEXT GLES2ProgramUniform3uivEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform4fEXT(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat); #define glProgramUniform4fEXT GLES2ProgramUniform4fEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform4fvEXT(GLuint, GLint, GLsizei, const GLfloat *); @@ -1567,34 +1578,23 @@ GL_APICALL void GL_APIENTRY GLES2ProgramUniform4iEXT(GLuint, GLint, GLint, GLint #define glProgramUniform4iEXT GLES2ProgramUniform4iEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniform4ivEXT(GLuint, GLint, GLsizei, const GLint *); #define glProgramUniform4ivEXT GLES2ProgramUniform4ivEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform4uiEXT(GLuint, GLint, GLuint, GLuint, GLuint, GLuint); -#define glProgramUniform4uiEXT GLES2ProgramUniform4uiEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniform4uivEXT(GLuint, GLint, GLsizei, const GLuint *); -#define glProgramUniform4uivEXT GLES2ProgramUniform4uivEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix2fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); #define glProgramUniformMatrix2fvEXT GLES2ProgramUniformMatrix2fvEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix2x3fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix2x3fvEXT GLES2ProgramUniformMatrix2x3fvEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix2x4fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix2x4fvEXT GLES2ProgramUniformMatrix2x4fvEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix3fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); #define glProgramUniformMatrix3fvEXT GLES2ProgramUniformMatrix3fvEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix3x2fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix3x2fvEXT GLES2ProgramUniformMatrix3x2fvEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix3x4fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix3x4fvEXT GLES2ProgramUniformMatrix3x4fvEXT GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix4fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); #define glProgramUniformMatrix4fvEXT GLES2ProgramUniformMatrix4fvEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix4x2fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix4x2fvEXT GLES2ProgramUniformMatrix4x2fvEXT -GL_APICALL void GL_APIENTRY GLES2ProgramUniformMatrix4x3fvEXT(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); -#define glProgramUniformMatrix4x3fvEXT GLES2ProgramUniformMatrix4x3fvEXT GL_APICALL void GL_APIENTRY GLES2UseProgramStagesEXT(GLuint, GLbitfield, GLuint); #define glUseProgramStagesEXT GLES2UseProgramStagesEXT GL_APICALL void GL_APIENTRY GLES2ValidateProgramPipelineEXT(GLuint); #define glValidateProgramPipelineEXT GLES2ValidateProgramPipelineEXT #endif +/* GL_EXT_shader_framebuffer_fetch */ +#ifndef GL_EXT_shader_framebuffer_fetch +#define GL_EXT_shader_framebuffer_fetch 1 +#endif + /* GL_EXT_shader_texture_lod */ #ifndef GL_EXT_shader_texture_lod #define GL_EXT_shader_texture_lod 1 @@ -1654,8 +1654,6 @@ GL_APICALL void GL_APIENTRY GLES2TexParameterIuivEXT(GLenum, GLenum, const GLuin /* GL_EXT_texture_storage */ #ifndef GL_EXT_texture_storage #define GL_EXT_texture_storage 1 -GL_APICALL void GL_APIENTRY GLES2TexStorage1DEXT(GLenum, GLsizei, GLenum, GLsizei); -#define glTexStorage1DEXT GLES2TexStorage1DEXT GL_APICALL void GL_APIENTRY GLES2TexStorage2DEXT(GLenum, GLsizei, GLenum, GLsizei, GLsizei); #define glTexStorage2DEXT GLES2TexStorage2DEXT GL_APICALL void GL_APIENTRY GLES2TexStorage3DEXT(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei); @@ -1722,6 +1720,11 @@ GL_APICALL void GL_APIENTRY GLES2PushDebugGroupKHR(GLenum, GLuint, GLsizei, cons #define glPushDebugGroupKHR GLES2PushDebugGroupKHR #endif +/* GL_KHR_no_error */ +#ifndef GL_KHR_no_error +#define GL_KHR_no_error 1 +#endif + /* GL_KHR_robust_buffer_access_behavior */ #ifndef GL_KHR_robust_buffer_access_behavior #define GL_KHR_robust_buffer_access_behavior 1 @@ -1863,6 +1866,11 @@ GL_APICALL void GL_APIENTRY GLES2ReadBufferNV(GLenum); #define GL_OES_element_index_uint 1 #endif +/* GL_OES_fbo_render_mipmap */ +#ifndef GL_OES_fbo_render_mipmap +#define GL_OES_fbo_render_mipmap 1 +#endif + /* GL_OES_mapbuffer */ #ifndef GL_OES_mapbuffer #define GL_OES_mapbuffer 1 diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatform.cpp b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatform.cpp index d7df7679f..0bc5c6371 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatform.cpp +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatform.cpp @@ -100,35 +100,21 @@ void flextGLInit() { flextglProgramUniform1fvEXT = reinterpret_cast(loader.load("glProgramUniform1fvEXT")); flextglProgramUniform1iEXT = reinterpret_cast(loader.load("glProgramUniform1iEXT")); flextglProgramUniform1ivEXT = reinterpret_cast(loader.load("glProgramUniform1ivEXT")); - flextglProgramUniform1uiEXT = reinterpret_cast(loader.load("glProgramUniform1uiEXT")); - flextglProgramUniform1uivEXT = reinterpret_cast(loader.load("glProgramUniform1uivEXT")); flextglProgramUniform2fEXT = reinterpret_cast(loader.load("glProgramUniform2fEXT")); flextglProgramUniform2fvEXT = reinterpret_cast(loader.load("glProgramUniform2fvEXT")); flextglProgramUniform2iEXT = reinterpret_cast(loader.load("glProgramUniform2iEXT")); flextglProgramUniform2ivEXT = reinterpret_cast(loader.load("glProgramUniform2ivEXT")); - flextglProgramUniform2uiEXT = reinterpret_cast(loader.load("glProgramUniform2uiEXT")); - flextglProgramUniform2uivEXT = reinterpret_cast(loader.load("glProgramUniform2uivEXT")); flextglProgramUniform3fEXT = reinterpret_cast(loader.load("glProgramUniform3fEXT")); flextglProgramUniform3fvEXT = reinterpret_cast(loader.load("glProgramUniform3fvEXT")); flextglProgramUniform3iEXT = reinterpret_cast(loader.load("glProgramUniform3iEXT")); flextglProgramUniform3ivEXT = reinterpret_cast(loader.load("glProgramUniform3ivEXT")); - flextglProgramUniform3uiEXT = reinterpret_cast(loader.load("glProgramUniform3uiEXT")); - flextglProgramUniform3uivEXT = reinterpret_cast(loader.load("glProgramUniform3uivEXT")); flextglProgramUniform4fEXT = reinterpret_cast(loader.load("glProgramUniform4fEXT")); flextglProgramUniform4fvEXT = reinterpret_cast(loader.load("glProgramUniform4fvEXT")); flextglProgramUniform4iEXT = reinterpret_cast(loader.load("glProgramUniform4iEXT")); flextglProgramUniform4ivEXT = reinterpret_cast(loader.load("glProgramUniform4ivEXT")); - flextglProgramUniform4uiEXT = reinterpret_cast(loader.load("glProgramUniform4uiEXT")); - flextglProgramUniform4uivEXT = reinterpret_cast(loader.load("glProgramUniform4uivEXT")); flextglProgramUniformMatrix2fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix2fvEXT")); - flextglProgramUniformMatrix2x3fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix2x3fvEXT")); - flextglProgramUniformMatrix2x4fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix2x4fvEXT")); flextglProgramUniformMatrix3fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix3fvEXT")); - flextglProgramUniformMatrix3x2fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix3x2fvEXT")); - flextglProgramUniformMatrix3x4fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix3x4fvEXT")); flextglProgramUniformMatrix4fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix4fvEXT")); - flextglProgramUniformMatrix4x2fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix4x2fvEXT")); - flextglProgramUniformMatrix4x3fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix4x3fvEXT")); flextglUseProgramStagesEXT = reinterpret_cast(loader.load("glUseProgramStagesEXT")); flextglValidateProgramPipelineEXT = reinterpret_cast(loader.load("glValidateProgramPipelineEXT")); @@ -143,12 +129,8 @@ void flextGLInit() { flextglTexParameterIuivEXT = reinterpret_cast(loader.load("glTexParameterIuivEXT")); /* GL_EXT_texture_storage */ - flextglTexStorage1DEXT = reinterpret_cast(loader.load("glTexStorage1DEXT")); flextglTexStorage2DEXT = reinterpret_cast(loader.load("glTexStorage2DEXT")); flextglTexStorage3DEXT = reinterpret_cast(loader.load("glTexStorage3DEXT")); - flextglTextureStorage1DEXT = reinterpret_cast(loader.load("glTextureStorage1DEXT")); - flextglTextureStorage2DEXT = reinterpret_cast(loader.load("glTextureStorage2DEXT")); - flextglTextureStorage3DEXT = reinterpret_cast(loader.load("glTextureStorage3DEXT")); /* GL_KHR_blend_equation_advanced */ flextglBlendBarrierKHR = reinterpret_cast(loader.load("glBlendBarrierKHR")); diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp index d94dd06d4..1c99e7def 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp @@ -59,35 +59,21 @@ #undef glProgramUniform1fvEXT #undef glProgramUniform1iEXT #undef glProgramUniform1ivEXT -#undef glProgramUniform1uiEXT -#undef glProgramUniform1uivEXT #undef glProgramUniform2fEXT #undef glProgramUniform2fvEXT #undef glProgramUniform2iEXT #undef glProgramUniform2ivEXT -#undef glProgramUniform2uiEXT -#undef glProgramUniform2uivEXT #undef glProgramUniform3fEXT #undef glProgramUniform3fvEXT #undef glProgramUniform3iEXT #undef glProgramUniform3ivEXT -#undef glProgramUniform3uiEXT -#undef glProgramUniform3uivEXT #undef glProgramUniform4fEXT #undef glProgramUniform4fvEXT #undef glProgramUniform4iEXT #undef glProgramUniform4ivEXT -#undef glProgramUniform4uiEXT -#undef glProgramUniform4uivEXT #undef glProgramUniformMatrix2fvEXT -#undef glProgramUniformMatrix2x3fvEXT -#undef glProgramUniformMatrix2x4fvEXT #undef glProgramUniformMatrix3fvEXT -#undef glProgramUniformMatrix3x2fvEXT -#undef glProgramUniformMatrix3x4fvEXT #undef glProgramUniformMatrix4fvEXT -#undef glProgramUniformMatrix4x2fvEXT -#undef glProgramUniformMatrix4x3fvEXT #undef glUseProgramStagesEXT #undef glValidateProgramPipelineEXT #undef glGetSamplerParameterIivEXT @@ -98,12 +84,8 @@ #undef glSamplerParameterIuivEXT #undef glTexParameterIivEXT #undef glTexParameterIuivEXT -#undef glTexStorage1DEXT #undef glTexStorage2DEXT #undef glTexStorage3DEXT -#undef glTextureStorage1DEXT -#undef glTextureStorage2DEXT -#undef glTextureStorage3DEXT #undef glBlendBarrierKHR #undef glDebugMessageCallbackKHR #undef glDebugMessageControlKHR @@ -146,6 +128,9 @@ #include void flextGLInit() { + /* Work around missing glTexStorage3D (can't be used anyway because GLES2 + on iOS doesn't support OES_texture_3D) */ + constexpr void(*glTexStorage3DEXT)() = nullptr; /* GL_ANGLE_framebuffer_blit */ #if GL_ANGLE_framebuffer_blit @@ -272,35 +257,21 @@ void flextGLInit() { flextglProgramUniform1fvEXT = reinterpret_cast(glProgramUniform1fvEXT); flextglProgramUniform1iEXT = reinterpret_cast(glProgramUniform1iEXT); flextglProgramUniform1ivEXT = reinterpret_cast(glProgramUniform1ivEXT); - flextglProgramUniform1uiEXT = reinterpret_cast(glProgramUniform1uiEXT); - flextglProgramUniform1uivEXT = reinterpret_cast(glProgramUniform1uivEXT); flextglProgramUniform2fEXT = reinterpret_cast(glProgramUniform2fEXT); flextglProgramUniform2fvEXT = reinterpret_cast(glProgramUniform2fvEXT); flextglProgramUniform2iEXT = reinterpret_cast(glProgramUniform2iEXT); flextglProgramUniform2ivEXT = reinterpret_cast(glProgramUniform2ivEXT); - flextglProgramUniform2uiEXT = reinterpret_cast(glProgramUniform2uiEXT); - flextglProgramUniform2uivEXT = reinterpret_cast(glProgramUniform2uivEXT); flextglProgramUniform3fEXT = reinterpret_cast(glProgramUniform3fEXT); flextglProgramUniform3fvEXT = reinterpret_cast(glProgramUniform3fvEXT); flextglProgramUniform3iEXT = reinterpret_cast(glProgramUniform3iEXT); flextglProgramUniform3ivEXT = reinterpret_cast(glProgramUniform3ivEXT); - flextglProgramUniform3uiEXT = reinterpret_cast(glProgramUniform3uiEXT); - flextglProgramUniform3uivEXT = reinterpret_cast(glProgramUniform3uivEXT); flextglProgramUniform4fEXT = reinterpret_cast(glProgramUniform4fEXT); flextglProgramUniform4fvEXT = reinterpret_cast(glProgramUniform4fvEXT); flextglProgramUniform4iEXT = reinterpret_cast(glProgramUniform4iEXT); flextglProgramUniform4ivEXT = reinterpret_cast(glProgramUniform4ivEXT); - flextglProgramUniform4uiEXT = reinterpret_cast(glProgramUniform4uiEXT); - flextglProgramUniform4uivEXT = reinterpret_cast(glProgramUniform4uivEXT); flextglProgramUniformMatrix2fvEXT = reinterpret_cast(glProgramUniformMatrix2fvEXT); - flextglProgramUniformMatrix2x3fvEXT = reinterpret_cast(glProgramUniformMatrix2x3fvEXT); - flextglProgramUniformMatrix2x4fvEXT = reinterpret_cast(glProgramUniformMatrix2x4fvEXT); flextglProgramUniformMatrix3fvEXT = reinterpret_cast(glProgramUniformMatrix3fvEXT); - flextglProgramUniformMatrix3x2fvEXT = reinterpret_cast(glProgramUniformMatrix3x2fvEXT); - flextglProgramUniformMatrix3x4fvEXT = reinterpret_cast(glProgramUniformMatrix3x4fvEXT); flextglProgramUniformMatrix4fvEXT = reinterpret_cast(glProgramUniformMatrix4fvEXT); - flextglProgramUniformMatrix4x2fvEXT = reinterpret_cast(glProgramUniformMatrix4x2fvEXT); - flextglProgramUniformMatrix4x3fvEXT = reinterpret_cast(glProgramUniformMatrix4x3fvEXT); flextglUseProgramStagesEXT = reinterpret_cast(glUseProgramStagesEXT); flextglValidateProgramPipelineEXT = reinterpret_cast(glValidateProgramPipelineEXT); #endif @@ -319,12 +290,8 @@ void flextGLInit() { /* GL_EXT_texture_storage */ #if GL_EXT_texture_storage - flextglTexStorage1DEXT = reinterpret_cast(glTexStorage1DEXT); flextglTexStorage2DEXT = reinterpret_cast(glTexStorage2DEXT); flextglTexStorage3DEXT = reinterpret_cast(glTexStorage3DEXT); - flextglTextureStorage1DEXT = reinterpret_cast(glTextureStorage1DEXT); - flextglTextureStorage2DEXT = reinterpret_cast(glTextureStorage2DEXT); - flextglTextureStorage3DEXT = reinterpret_cast(glTextureStorage3DEXT); #endif /* GL_KHR_blend_equation_advanced */ diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp.template b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp.template index 2d5982016..a038a4f0a 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp.template +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformIOS.cpp.template @@ -12,6 +12,9 @@ #include void flextGLInit() { + /* Work around missing glTexStorage3D (can't be used anyway because GLES2 + on iOS doesn't support OES_texture_3D) */ + constexpr void(*glTexStorage3DEXT)() = nullptr; @for category,funcs in functions: @if funcs and category not in ['ES_VERSION_2_0']: diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformWindowsDesktop.cpp b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformWindowsDesktop.cpp new file mode 100644 index 000000000..fed940656 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformWindowsDesktop.cpp @@ -0,0 +1,297 @@ +#include "flextGLWindowsDesktop.h" + +#include +#include + +#include "Magnum/Platform/Implementation/OpenGLFunctionLoader.h" + +void flextGLInit() { + Magnum::Platform::Implementation::OpenGLFunctionLoader loader; + + /* GL_ANGLE_framebuffer_blit */ + flextglBlitFramebufferANGLE = reinterpret_cast(loader.load("glBlitFramebufferANGLE")); + + /* GL_ANGLE_framebuffer_multisample */ + flextglRenderbufferStorageMultisampleANGLE = reinterpret_cast(loader.load("glRenderbufferStorageMultisampleANGLE")); + + /* GL_ANGLE_instanced_arrays */ + flextglDrawArraysInstancedANGLE = reinterpret_cast(loader.load("glDrawArraysInstancedANGLE")); + flextglDrawElementsInstancedANGLE = reinterpret_cast(loader.load("glDrawElementsInstancedANGLE")); + flextglVertexAttribDivisorANGLE = reinterpret_cast(loader.load("glVertexAttribDivisorANGLE")); + + /* GL_APPLE_framebuffer_multisample */ + flextglRenderbufferStorageMultisampleAPPLE = reinterpret_cast(loader.load("glRenderbufferStorageMultisampleAPPLE")); + flextglResolveMultisampleFramebufferAPPLE = reinterpret_cast(loader.load("glResolveMultisampleFramebufferAPPLE")); + + /* GL_ES_VERSION_2_0 */ + flextglActiveTexture = reinterpret_cast(loader.load("glActiveTexture")); + flextglAttachShader = reinterpret_cast(loader.load("glAttachShader")); + flextglBindAttribLocation = reinterpret_cast(loader.load("glBindAttribLocation")); + flextglBindBuffer = reinterpret_cast(loader.load("glBindBuffer")); + flextglBindFramebuffer = reinterpret_cast(loader.load("glBindFramebuffer")); + flextglBindRenderbuffer = reinterpret_cast(loader.load("glBindRenderbuffer")); + flextglBlendColor = reinterpret_cast(loader.load("glBlendColor")); + flextglBlendEquation = reinterpret_cast(loader.load("glBlendEquation")); + flextglBlendEquationSeparate = reinterpret_cast(loader.load("glBlendEquationSeparate")); + flextglBlendFuncSeparate = reinterpret_cast(loader.load("glBlendFuncSeparate")); + flextglBufferData = reinterpret_cast(loader.load("glBufferData")); + flextglBufferSubData = reinterpret_cast(loader.load("glBufferSubData")); + flextglCheckFramebufferStatus = reinterpret_cast(loader.load("glCheckFramebufferStatus")); + flextglClearDepthf = reinterpret_cast(loader.load("glClearDepthf")); + flextglCompileShader = reinterpret_cast(loader.load("glCompileShader")); + flextglCompressedTexImage2D = reinterpret_cast(loader.load("glCompressedTexImage2D")); + flextglCompressedTexSubImage2D = reinterpret_cast(loader.load("glCompressedTexSubImage2D")); + flextglCreateProgram = reinterpret_cast(loader.load("glCreateProgram")); + flextglCreateShader = reinterpret_cast(loader.load("glCreateShader")); + flextglDeleteBuffers = reinterpret_cast(loader.load("glDeleteBuffers")); + flextglDeleteFramebuffers = reinterpret_cast(loader.load("glDeleteFramebuffers")); + flextglDeleteProgram = reinterpret_cast(loader.load("glDeleteProgram")); + flextglDeleteRenderbuffers = reinterpret_cast(loader.load("glDeleteRenderbuffers")); + flextglDeleteShader = reinterpret_cast(loader.load("glDeleteShader")); + flextglDepthRangef = reinterpret_cast(loader.load("glDepthRangef")); + flextglDetachShader = reinterpret_cast(loader.load("glDetachShader")); + flextglDisableVertexAttribArray = reinterpret_cast(loader.load("glDisableVertexAttribArray")); + flextglEnableVertexAttribArray = reinterpret_cast(loader.load("glEnableVertexAttribArray")); + flextglFramebufferRenderbuffer = reinterpret_cast(loader.load("glFramebufferRenderbuffer")); + flextglFramebufferTexture2D = reinterpret_cast(loader.load("glFramebufferTexture2D")); + flextglGenBuffers = reinterpret_cast(loader.load("glGenBuffers")); + flextglGenFramebuffers = reinterpret_cast(loader.load("glGenFramebuffers")); + flextglGenRenderbuffers = reinterpret_cast(loader.load("glGenRenderbuffers")); + flextglGenerateMipmap = reinterpret_cast(loader.load("glGenerateMipmap")); + flextglGetActiveAttrib = reinterpret_cast(loader.load("glGetActiveAttrib")); + flextglGetActiveUniform = reinterpret_cast(loader.load("glGetActiveUniform")); + flextglGetAttachedShaders = reinterpret_cast(loader.load("glGetAttachedShaders")); + flextglGetAttribLocation = reinterpret_cast(loader.load("glGetAttribLocation")); + flextglGetBufferParameteriv = reinterpret_cast(loader.load("glGetBufferParameteriv")); + flextglGetFramebufferAttachmentParameteriv = reinterpret_cast(loader.load("glGetFramebufferAttachmentParameteriv")); + flextglGetProgramInfoLog = reinterpret_cast(loader.load("glGetProgramInfoLog")); + flextglGetProgramiv = reinterpret_cast(loader.load("glGetProgramiv")); + flextglGetRenderbufferParameteriv = reinterpret_cast(loader.load("glGetRenderbufferParameteriv")); + flextglGetShaderInfoLog = reinterpret_cast(loader.load("glGetShaderInfoLog")); + flextglGetShaderPrecisionFormat = reinterpret_cast(loader.load("glGetShaderPrecisionFormat")); + flextglGetShaderSource = reinterpret_cast(loader.load("glGetShaderSource")); + flextglGetShaderiv = reinterpret_cast(loader.load("glGetShaderiv")); + flextglGetUniformLocation = reinterpret_cast(loader.load("glGetUniformLocation")); + flextglGetUniformfv = reinterpret_cast(loader.load("glGetUniformfv")); + flextglGetUniformiv = reinterpret_cast(loader.load("glGetUniformiv")); + flextglGetVertexAttribPointerv = reinterpret_cast(loader.load("glGetVertexAttribPointerv")); + flextglGetVertexAttribfv = reinterpret_cast(loader.load("glGetVertexAttribfv")); + flextglGetVertexAttribiv = reinterpret_cast(loader.load("glGetVertexAttribiv")); + flextglIsBuffer = reinterpret_cast(loader.load("glIsBuffer")); + flextglIsFramebuffer = reinterpret_cast(loader.load("glIsFramebuffer")); + flextglIsProgram = reinterpret_cast(loader.load("glIsProgram")); + flextglIsRenderbuffer = reinterpret_cast(loader.load("glIsRenderbuffer")); + flextglIsShader = reinterpret_cast(loader.load("glIsShader")); + flextglLinkProgram = reinterpret_cast(loader.load("glLinkProgram")); + flextglReleaseShaderCompiler = reinterpret_cast(loader.load("glReleaseShaderCompiler")); + flextglRenderbufferStorage = reinterpret_cast(loader.load("glRenderbufferStorage")); + flextglSampleCoverage = reinterpret_cast(loader.load("glSampleCoverage")); + flextglShaderBinary = reinterpret_cast(loader.load("glShaderBinary")); + flextglShaderSource = reinterpret_cast(loader.load("glShaderSource")); + flextglStencilFuncSeparate = reinterpret_cast(loader.load("glStencilFuncSeparate")); + flextglStencilMaskSeparate = reinterpret_cast(loader.load("glStencilMaskSeparate")); + flextglStencilOpSeparate = reinterpret_cast(loader.load("glStencilOpSeparate")); + flextglUniform1f = reinterpret_cast(loader.load("glUniform1f")); + flextglUniform1fv = reinterpret_cast(loader.load("glUniform1fv")); + flextglUniform1i = reinterpret_cast(loader.load("glUniform1i")); + flextglUniform1iv = reinterpret_cast(loader.load("glUniform1iv")); + flextglUniform2f = reinterpret_cast(loader.load("glUniform2f")); + flextglUniform2fv = reinterpret_cast(loader.load("glUniform2fv")); + flextglUniform2i = reinterpret_cast(loader.load("glUniform2i")); + flextglUniform2iv = reinterpret_cast(loader.load("glUniform2iv")); + flextglUniform3f = reinterpret_cast(loader.load("glUniform3f")); + flextglUniform3fv = reinterpret_cast(loader.load("glUniform3fv")); + flextglUniform3i = reinterpret_cast(loader.load("glUniform3i")); + flextglUniform3iv = reinterpret_cast(loader.load("glUniform3iv")); + flextglUniform4f = reinterpret_cast(loader.load("glUniform4f")); + flextglUniform4fv = reinterpret_cast(loader.load("glUniform4fv")); + flextglUniform4i = reinterpret_cast(loader.load("glUniform4i")); + flextglUniform4iv = reinterpret_cast(loader.load("glUniform4iv")); + flextglUniformMatrix2fv = reinterpret_cast(loader.load("glUniformMatrix2fv")); + flextglUniformMatrix3fv = reinterpret_cast(loader.load("glUniformMatrix3fv")); + flextglUniformMatrix4fv = reinterpret_cast(loader.load("glUniformMatrix4fv")); + flextglUseProgram = reinterpret_cast(loader.load("glUseProgram")); + flextglValidateProgram = reinterpret_cast(loader.load("glValidateProgram")); + flextglVertexAttrib1f = reinterpret_cast(loader.load("glVertexAttrib1f")); + flextglVertexAttrib1fv = reinterpret_cast(loader.load("glVertexAttrib1fv")); + flextglVertexAttrib2f = reinterpret_cast(loader.load("glVertexAttrib2f")); + flextglVertexAttrib2fv = reinterpret_cast(loader.load("glVertexAttrib2fv")); + flextglVertexAttrib3f = reinterpret_cast(loader.load("glVertexAttrib3f")); + flextglVertexAttrib3fv = reinterpret_cast(loader.load("glVertexAttrib3fv")); + flextglVertexAttrib4f = reinterpret_cast(loader.load("glVertexAttrib4f")); + flextglVertexAttrib4fv = reinterpret_cast(loader.load("glVertexAttrib4fv")); + flextglVertexAttribPointer = reinterpret_cast(loader.load("glVertexAttribPointer")); + + /* GL_EXT_debug_label */ + flextglGetObjectLabelEXT = reinterpret_cast(loader.load("glGetObjectLabelEXT")); + flextglLabelObjectEXT = reinterpret_cast(loader.load("glLabelObjectEXT")); + + /* GL_EXT_debug_marker */ + flextglInsertEventMarkerEXT = reinterpret_cast(loader.load("glInsertEventMarkerEXT")); + flextglPopGroupMarkerEXT = reinterpret_cast(loader.load("glPopGroupMarkerEXT")); + flextglPushGroupMarkerEXT = reinterpret_cast(loader.load("glPushGroupMarkerEXT")); + + /* GL_EXT_discard_framebuffer */ + flextglDiscardFramebufferEXT = reinterpret_cast(loader.load("glDiscardFramebufferEXT")); + + /* GL_EXT_disjoint_timer_query */ + flextglGetQueryObjecti64vEXT = reinterpret_cast(loader.load("glGetQueryObjecti64vEXT")); + flextglGetQueryObjectivEXT = reinterpret_cast(loader.load("glGetQueryObjectivEXT")); + flextglGetQueryObjectui64vEXT = reinterpret_cast(loader.load("glGetQueryObjectui64vEXT")); + flextglQueryCounterEXT = reinterpret_cast(loader.load("glQueryCounterEXT")); + + /* GL_EXT_draw_buffers */ + flextglDrawBuffersEXT = reinterpret_cast(loader.load("glDrawBuffersEXT")); + + /* GL_EXT_draw_buffers_indexed */ + flextglBlendEquationSeparateiEXT = reinterpret_cast(loader.load("glBlendEquationSeparateiEXT")); + flextglBlendEquationiEXT = reinterpret_cast(loader.load("glBlendEquationiEXT")); + flextglBlendFuncSeparateiEXT = reinterpret_cast(loader.load("glBlendFuncSeparateiEXT")); + flextglBlendFunciEXT = reinterpret_cast(loader.load("glBlendFunciEXT")); + flextglColorMaskiEXT = reinterpret_cast(loader.load("glColorMaskiEXT")); + flextglDisableiEXT = reinterpret_cast(loader.load("glDisableiEXT")); + flextglEnableiEXT = reinterpret_cast(loader.load("glEnableiEXT")); + flextglIsEnablediEXT = reinterpret_cast(loader.load("glIsEnablediEXT")); + + /* GL_EXT_instanced_arrays */ + flextglDrawArraysInstancedEXT = reinterpret_cast(loader.load("glDrawArraysInstancedEXT")); + flextglDrawElementsInstancedEXT = reinterpret_cast(loader.load("glDrawElementsInstancedEXT")); + flextglVertexAttribDivisorEXT = reinterpret_cast(loader.load("glVertexAttribDivisorEXT")); + + /* GL_EXT_map_buffer_range */ + flextglFlushMappedBufferRangeEXT = reinterpret_cast(loader.load("glFlushMappedBufferRangeEXT")); + flextglMapBufferRangeEXT = reinterpret_cast(loader.load("glMapBufferRangeEXT")); + + /* GL_EXT_multi_draw_arrays */ + flextglMultiDrawArraysEXT = reinterpret_cast(loader.load("glMultiDrawArraysEXT")); + flextglMultiDrawElementsEXT = reinterpret_cast(loader.load("glMultiDrawElementsEXT")); + + /* GL_EXT_multisampled_render_to_texture */ + flextglFramebufferTexture2DMultisampleEXT = reinterpret_cast(loader.load("glFramebufferTexture2DMultisampleEXT")); + flextglRenderbufferStorageMultisampleEXT = reinterpret_cast(loader.load("glRenderbufferStorageMultisampleEXT")); + + /* GL_EXT_occlusion_query_boolean */ + flextglBeginQueryEXT = reinterpret_cast(loader.load("glBeginQueryEXT")); + flextglDeleteQueriesEXT = reinterpret_cast(loader.load("glDeleteQueriesEXT")); + flextglEndQueryEXT = reinterpret_cast(loader.load("glEndQueryEXT")); + flextglGenQueriesEXT = reinterpret_cast(loader.load("glGenQueriesEXT")); + flextglGetQueryObjectuivEXT = reinterpret_cast(loader.load("glGetQueryObjectuivEXT")); + flextglGetQueryivEXT = reinterpret_cast(loader.load("glGetQueryivEXT")); + flextglIsQueryEXT = reinterpret_cast(loader.load("glIsQueryEXT")); + + /* GL_EXT_robustness */ + flextglGetGraphicsResetStatusEXT = reinterpret_cast(loader.load("glGetGraphicsResetStatusEXT")); + flextglGetnUniformfvEXT = reinterpret_cast(loader.load("glGetnUniformfvEXT")); + flextglGetnUniformivEXT = reinterpret_cast(loader.load("glGetnUniformivEXT")); + flextglReadnPixelsEXT = reinterpret_cast(loader.load("glReadnPixelsEXT")); + + /* GL_EXT_separate_shader_objects */ + flextglActiveShaderProgramEXT = reinterpret_cast(loader.load("glActiveShaderProgramEXT")); + flextglBindProgramPipelineEXT = reinterpret_cast(loader.load("glBindProgramPipelineEXT")); + flextglCreateShaderProgramvEXT = reinterpret_cast(loader.load("glCreateShaderProgramvEXT")); + flextglDeleteProgramPipelinesEXT = reinterpret_cast(loader.load("glDeleteProgramPipelinesEXT")); + flextglGenProgramPipelinesEXT = reinterpret_cast(loader.load("glGenProgramPipelinesEXT")); + flextglGetProgramPipelineInfoLogEXT = reinterpret_cast(loader.load("glGetProgramPipelineInfoLogEXT")); + flextglGetProgramPipelineivEXT = reinterpret_cast(loader.load("glGetProgramPipelineivEXT")); + flextglIsProgramPipelineEXT = reinterpret_cast(loader.load("glIsProgramPipelineEXT")); + flextglProgramParameteriEXT = reinterpret_cast(loader.load("glProgramParameteriEXT")); + flextglProgramUniform1fEXT = reinterpret_cast(loader.load("glProgramUniform1fEXT")); + flextglProgramUniform1fvEXT = reinterpret_cast(loader.load("glProgramUniform1fvEXT")); + flextglProgramUniform1iEXT = reinterpret_cast(loader.load("glProgramUniform1iEXT")); + flextglProgramUniform1ivEXT = reinterpret_cast(loader.load("glProgramUniform1ivEXT")); + flextglProgramUniform2fEXT = reinterpret_cast(loader.load("glProgramUniform2fEXT")); + flextglProgramUniform2fvEXT = reinterpret_cast(loader.load("glProgramUniform2fvEXT")); + flextglProgramUniform2iEXT = reinterpret_cast(loader.load("glProgramUniform2iEXT")); + flextglProgramUniform2ivEXT = reinterpret_cast(loader.load("glProgramUniform2ivEXT")); + flextglProgramUniform3fEXT = reinterpret_cast(loader.load("glProgramUniform3fEXT")); + flextglProgramUniform3fvEXT = reinterpret_cast(loader.load("glProgramUniform3fvEXT")); + flextglProgramUniform3iEXT = reinterpret_cast(loader.load("glProgramUniform3iEXT")); + flextglProgramUniform3ivEXT = reinterpret_cast(loader.load("glProgramUniform3ivEXT")); + flextglProgramUniform4fEXT = reinterpret_cast(loader.load("glProgramUniform4fEXT")); + flextglProgramUniform4fvEXT = reinterpret_cast(loader.load("glProgramUniform4fvEXT")); + flextglProgramUniform4iEXT = reinterpret_cast(loader.load("glProgramUniform4iEXT")); + flextglProgramUniform4ivEXT = reinterpret_cast(loader.load("glProgramUniform4ivEXT")); + flextglProgramUniformMatrix2fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix2fvEXT")); + flextglProgramUniformMatrix3fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix3fvEXT")); + flextglProgramUniformMatrix4fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix4fvEXT")); + flextglUseProgramStagesEXT = reinterpret_cast(loader.load("glUseProgramStagesEXT")); + flextglValidateProgramPipelineEXT = reinterpret_cast(loader.load("glValidateProgramPipelineEXT")); + + /* GL_EXT_texture_border_clamp */ + flextglGetSamplerParameterIivEXT = reinterpret_cast(loader.load("glGetSamplerParameterIivEXT")); + flextglGetSamplerParameterIuivEXT = reinterpret_cast(loader.load("glGetSamplerParameterIuivEXT")); + flextglGetTexParameterIivEXT = reinterpret_cast(loader.load("glGetTexParameterIivEXT")); + flextglGetTexParameterIuivEXT = reinterpret_cast(loader.load("glGetTexParameterIuivEXT")); + flextglSamplerParameterIivEXT = reinterpret_cast(loader.load("glSamplerParameterIivEXT")); + flextglSamplerParameterIuivEXT = reinterpret_cast(loader.load("glSamplerParameterIuivEXT")); + flextglTexParameterIivEXT = reinterpret_cast(loader.load("glTexParameterIivEXT")); + flextglTexParameterIuivEXT = reinterpret_cast(loader.load("glTexParameterIuivEXT")); + + /* GL_EXT_texture_storage */ + flextglTexStorage2DEXT = reinterpret_cast(loader.load("glTexStorage2DEXT")); + flextglTexStorage3DEXT = reinterpret_cast(loader.load("glTexStorage3DEXT")); + + /* GL_KHR_blend_equation_advanced */ + flextglBlendBarrierKHR = reinterpret_cast(loader.load("glBlendBarrierKHR")); + + /* GL_KHR_debug */ + flextglDebugMessageCallbackKHR = reinterpret_cast(loader.load("glDebugMessageCallbackKHR")); + flextglDebugMessageControlKHR = reinterpret_cast(loader.load("glDebugMessageControlKHR")); + flextglDebugMessageInsertKHR = reinterpret_cast(loader.load("glDebugMessageInsertKHR")); + flextglGetDebugMessageLogKHR = reinterpret_cast(loader.load("glGetDebugMessageLogKHR")); + flextglGetObjectLabelKHR = reinterpret_cast(loader.load("glGetObjectLabelKHR")); + flextglGetObjectPtrLabelKHR = reinterpret_cast(loader.load("glGetObjectPtrLabelKHR")); + flextglGetPointervKHR = reinterpret_cast(loader.load("glGetPointervKHR")); + flextglObjectLabelKHR = reinterpret_cast(loader.load("glObjectLabelKHR")); + flextglObjectPtrLabelKHR = reinterpret_cast(loader.load("glObjectPtrLabelKHR")); + flextglPopDebugGroupKHR = reinterpret_cast(loader.load("glPopDebugGroupKHR")); + flextglPushDebugGroupKHR = reinterpret_cast(loader.load("glPushDebugGroupKHR")); + + /* GL_KHR_robustness */ + flextglGetGraphicsResetStatusKHR = reinterpret_cast(loader.load("glGetGraphicsResetStatusKHR")); + flextglGetnUniformfvKHR = reinterpret_cast(loader.load("glGetnUniformfvKHR")); + flextglGetnUniformivKHR = reinterpret_cast(loader.load("glGetnUniformivKHR")); + flextglGetnUniformuivKHR = reinterpret_cast(loader.load("glGetnUniformuivKHR")); + flextglReadnPixelsKHR = reinterpret_cast(loader.load("glReadnPixelsKHR")); + + /* GL_NV_draw_buffers */ + flextglDrawBuffersNV = reinterpret_cast(loader.load("glDrawBuffersNV")); + + /* GL_NV_draw_instanced */ + flextglDrawArraysInstancedNV = reinterpret_cast(loader.load("glDrawArraysInstancedNV")); + flextglDrawElementsInstancedNV = reinterpret_cast(loader.load("glDrawElementsInstancedNV")); + + /* GL_NV_framebuffer_blit */ + flextglBlitFramebufferNV = reinterpret_cast(loader.load("glBlitFramebufferNV")); + + /* GL_NV_framebuffer_multisample */ + flextglRenderbufferStorageMultisampleNV = reinterpret_cast(loader.load("glRenderbufferStorageMultisampleNV")); + + /* GL_NV_instanced_arrays */ + flextglVertexAttribDivisorNV = reinterpret_cast(loader.load("glVertexAttribDivisorNV")); + + /* GL_NV_polygon_mode */ + flextglPolygonModeNV = reinterpret_cast(loader.load("glPolygonModeNV")); + + /* GL_NV_read_buffer */ + flextglReadBufferNV = reinterpret_cast(loader.load("glReadBufferNV")); + + /* GL_OES_mapbuffer */ + flextglGetBufferPointervOES = reinterpret_cast(loader.load("glGetBufferPointervOES")); + flextglMapBufferOES = reinterpret_cast(loader.load("glMapBufferOES")); + flextglUnmapBufferOES = reinterpret_cast(loader.load("glUnmapBufferOES")); + + /* GL_OES_texture_3D */ + flextglCompressedTexImage3DOES = reinterpret_cast(loader.load("glCompressedTexImage3DOES")); + flextglCompressedTexSubImage3DOES = reinterpret_cast(loader.load("glCompressedTexSubImage3DOES")); + flextglCopyTexSubImage3DOES = reinterpret_cast(loader.load("glCopyTexSubImage3DOES")); + flextglFramebufferTexture3DOES = reinterpret_cast(loader.load("glFramebufferTexture3DOES")); + flextglTexImage3DOES = reinterpret_cast(loader.load("glTexImage3DOES")); + flextglTexSubImage3DOES = reinterpret_cast(loader.load("glTexSubImage3DOES")); + + /* GL_OES_vertex_array_object */ + flextglBindVertexArrayOES = reinterpret_cast(loader.load("glBindVertexArrayOES")); + flextglDeleteVertexArraysOES = reinterpret_cast(loader.load("glDeleteVertexArraysOES")); + flextglGenVertexArraysOES = reinterpret_cast(loader.load("glGenVertexArraysOES")); + flextglIsVertexArrayOES = reinterpret_cast(loader.load("glIsVertexArrayOES")); +} diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformWindowsDesktop.cpp.template b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformWindowsDesktop.cpp.template new file mode 100644 index 000000000..8af659565 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLPlatformWindowsDesktop.cpp.template @@ -0,0 +1,23 @@ +@require(passthru, functions, enums, options, version, extensions) +#include "flextGLWindowsDesktop.h" + +#include +#include + +#include "Magnum/Platform/Implementation/OpenGLFunctionLoader.h" + +void flextGLInit() { + Magnum::Platform::Implementation::OpenGLFunctionLoader loader; + @for category,funcs in functions: + @if funcs: + + /* GL_@category */ + @for f in funcs: + @if f.name not in ['BlendFunc', 'Clear', 'ClearColor', 'ClearDepth', 'ClearStencil', 'ColorMask', 'CullFace', 'DepthFunc', 'DepthMask', 'DepthRange', 'Disable', 'DrawBuffer', 'Enable', 'Finish', 'Flush', 'FrontFace', 'GetBooleanv', 'GetDoublev', 'GetError', 'GetFloatv', 'GetIntegerv', 'GetString', 'GetTexImage', 'GetTexLevelParameterfv', 'GetTexLevelParameteriv', 'GetTexParameterfv', 'GetTexParameteriv', 'Hint', 'IsEnabled', 'LineWidth', 'LogicOp', 'PixelStoref', 'PixelStorei', 'PointSize', 'PolygonMode', 'ReadBuffer', 'ReadPixels', 'Scissor', 'StencilFunc', 'StencilMask', 'StencilOp', 'TexImage1D', 'TexImage2D', 'TexParameterf', 'TexParameterfv', 'TexParameteri', 'TexParameteriv', 'Viewport', 'BindTexture', 'CopyTexImage1D', 'CopyTexImage2D', 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'DeleteTextures', 'DrawArrays', 'DrawElements', 'GenTextures', 'IsTexture', 'PolygonOffset', 'TexSubImage1D', 'TexSubImage2D']: + flextgl@f.name = reinterpret_cast<@f.returntype\ +(APIENTRY*)(@f.param_type_list_string())>(loader.load("gl@f.name")); + @end + @end + @end + @end +} diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.cpp b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.cpp new file mode 100644 index 000000000..52038efea --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.cpp @@ -0,0 +1,296 @@ +#include "flextGLWindowsDesktop.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* GL_ANGLE_framebuffer_blit */ +FLEXTGL_EXPORT void(APIENTRY *flextglBlitFramebufferANGLE)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum) = nullptr; + +/* GL_ANGLE_framebuffer_multisample */ +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleANGLE)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; + +/* GL_ANGLE_instanced_arrays */ +FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstancedANGLE)(GLenum, GLint, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstancedANGLE)(GLenum, GLsizei, GLenum, const void *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisorANGLE)(GLuint, GLuint) = nullptr; + +/* GL_APPLE_framebuffer_multisample */ +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleAPPLE)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglResolveMultisampleFramebufferAPPLE)(void) = nullptr; + +/* GL_ES_VERSION_2_0 */ +FLEXTGL_EXPORT void(APIENTRY *flextglActiveTexture)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglAttachShader)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindAttribLocation)(GLuint, GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindBuffer)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindFramebuffer)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindRenderbuffer)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendColor)(GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquation)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparate)(GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparate)(GLenum, GLenum, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBufferData)(GLenum, GLsizeiptr, const void *, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBufferSubData)(GLenum, GLintptr, GLsizeiptr, const void *) = nullptr; +FLEXTGL_EXPORT GLenum(APIENTRY *flextglCheckFramebufferStatus)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglClearDepthf)(GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompileShader)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage2D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateProgram)(void) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShader)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteBuffers)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteFramebuffers)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteRenderbuffers)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteShader)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDepthRangef)(GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDetachShader)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDisableVertexAttribArray)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEnableVertexAttribArray)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenBuffers)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenFramebuffers)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenRenderbuffers)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenerateMipmap)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveAttrib)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniform)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetAttachedShaders)(GLuint, GLsizei, GLsizei *, GLuint *) = nullptr; +FLEXTGL_EXPORT GLint(APIENTRY *flextglGetAttribLocation)(GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferParameteriv)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetFramebufferAttachmentParameteriv)(GLenum, GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetRenderbufferParameteriv)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderPrecisionFormat)(GLenum, GLenum, GLint *, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderSource)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLint(APIENTRY *flextglGetUniformLocation)(GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformfv)(GLuint, GLint, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformiv)(GLuint, GLint, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribPointerv)(GLuint, GLenum, void **) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribfv)(GLuint, GLenum, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsBuffer)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsFramebuffer)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsRenderbuffer)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsShader)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglLinkProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglReleaseShaderCompiler)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSampleCoverage)(GLfloat, GLboolean) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglShaderBinary)(GLsizei, const GLuint *, GLenum, const void *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglShaderSource)(GLuint, GLsizei, const GLchar *const*, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglStencilMaskSeparate)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1f)(GLint, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1i)(GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2f)(GLint, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2i)(GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3f)(GLint, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3i)(GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4i)(GLint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUseProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1f)(GLuint, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2f)(GLuint, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3f)(GLuint, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4f)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *) = nullptr; + +/* GL_EXT_debug_label */ +FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelEXT)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglLabelObjectEXT)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; + +/* GL_EXT_debug_marker */ +FLEXTGL_EXPORT void(APIENTRY *flextglInsertEventMarkerEXT)(GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPopGroupMarkerEXT)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPushGroupMarkerEXT)(GLsizei, const GLchar *) = nullptr; + +/* GL_EXT_discard_framebuffer */ +FLEXTGL_EXPORT void(APIENTRY *flextglDiscardFramebufferEXT)(GLenum, GLsizei, const GLenum *) = nullptr; + +/* GL_EXT_disjoint_timer_query */ +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjecti64vEXT)(GLuint, GLenum, GLint64 *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectivEXT)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectui64vEXT)(GLuint, GLenum, GLuint64 *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglQueryCounterEXT)(GLuint, GLenum) = nullptr; + +/* GL_EXT_draw_buffers */ +FLEXTGL_EXPORT void(APIENTRY *flextglDrawBuffersEXT)(GLsizei, const GLenum *) = nullptr; + +/* GL_EXT_draw_buffers_indexed */ +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparateiEXT)(GLuint, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationiEXT)(GLuint, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparateiEXT)(GLuint, GLenum, GLenum, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendFunciEXT)(GLuint, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglColorMaskiEXT)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDisableiEXT)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEnableiEXT)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsEnablediEXT)(GLenum, GLuint) = nullptr; + +/* GL_EXT_instanced_arrays */ +FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstancedEXT)(GLenum, GLint, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstancedEXT)(GLenum, GLsizei, GLenum, const void *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisorEXT)(GLuint, GLuint) = nullptr; + +/* GL_EXT_map_buffer_range */ +FLEXTGL_EXPORT void(APIENTRY *flextglFlushMappedBufferRangeEXT)(GLenum, GLintptr, GLsizeiptr) = nullptr; +FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferRangeEXT)(GLenum, GLintptr, GLsizeiptr, GLbitfield) = nullptr; + +/* GL_EXT_multi_draw_arrays */ +FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawArraysEXT)(GLenum, const GLint *, const GLsizei *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawElementsEXT)(GLenum, const GLsizei *, GLenum, const void *const*, GLsizei) = nullptr; + +/* GL_EXT_multisampled_render_to_texture */ +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2DMultisampleEXT)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; + +/* GL_EXT_occlusion_query_boolean */ +FLEXTGL_EXPORT void(APIENTRY *flextglBeginQueryEXT)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteQueriesEXT)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEndQueryEXT)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenQueriesEXT)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectuivEXT)(GLuint, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryivEXT)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsQueryEXT)(GLuint) = nullptr; + +/* GL_EXT_robustness */ +FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusEXT)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvEXT)(GLuint, GLint, GLsizei, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivEXT)(GLuint, GLint, GLsizei, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsEXT)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *) = nullptr; + +/* GL_EXT_separate_shader_objects */ +FLEXTGL_EXPORT void(APIENTRY *flextglActiveShaderProgramEXT)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindProgramPipelineEXT)(GLuint) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShaderProgramvEXT)(GLenum, GLsizei, const GLchar **) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgramPipelinesEXT)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenProgramPipelinesEXT)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineInfoLogEXT)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineivEXT)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgramPipelineEXT)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramParameteriEXT)(GLuint, GLenum, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fEXT)(GLuint, GLint, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iEXT)(GLuint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fEXT)(GLuint, GLint, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iEXT)(GLuint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iEXT)(GLuint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iEXT)(GLuint, GLint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStagesEXT)(GLuint, GLbitfield, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipelineEXT)(GLuint) = nullptr; + +/* GL_EXT_texture_border_clamp */ +FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIivEXT)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIuivEXT)(GLuint, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIivEXT)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIuivEXT)(GLenum, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIivEXT)(GLuint, GLenum, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIuivEXT)(GLuint, GLenum, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIivEXT)(GLenum, GLenum, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIuivEXT)(GLenum, GLenum, const GLuint *) = nullptr; + +/* GL_EXT_texture_storage */ +FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei) = nullptr; + +/* GL_KHR_blend_equation_advanced */ +FLEXTGL_EXPORT void(APIENTRY *flextglBlendBarrierKHR)(void) = nullptr; + +/* GL_KHR_debug */ +FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageCallbackKHR)(GLDEBUGPROCKHR, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageControlKHR)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageInsertKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetDebugMessageLogKHR)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelKHR)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectPtrLabelKHR)(const void *, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetPointervKHR)(GLenum, void **) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglObjectLabelKHR)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglObjectPtrLabelKHR)(const void *, GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPopDebugGroupKHR)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPushDebugGroupKHR)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; + +/* GL_KHR_robustness */ +FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusKHR)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvKHR)(GLuint, GLint, GLsizei, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivKHR)(GLuint, GLint, GLsizei, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformuivKHR)(GLuint, GLint, GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsKHR)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *) = nullptr; + +/* GL_NV_draw_buffers */ +FLEXTGL_EXPORT void(APIENTRY *flextglDrawBuffersNV)(GLsizei, const GLenum *) = nullptr; + +/* GL_NV_draw_instanced */ +FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstancedNV)(GLenum, GLint, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstancedNV)(GLenum, GLsizei, GLenum, const void *, GLsizei) = nullptr; + +/* GL_NV_framebuffer_blit */ +FLEXTGL_EXPORT void(APIENTRY *flextglBlitFramebufferNV)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum) = nullptr; + +/* GL_NV_framebuffer_multisample */ +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleNV)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; + +/* GL_NV_instanced_arrays */ +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisorNV)(GLuint, GLuint) = nullptr; + +/* GL_NV_polygon_mode */ +FLEXTGL_EXPORT void(APIENTRY *flextglPolygonModeNV)(GLenum, GLenum) = nullptr; + +/* GL_NV_read_buffer */ +FLEXTGL_EXPORT void(APIENTRY *flextglReadBufferNV)(GLenum) = nullptr; + +/* GL_OES_mapbuffer */ +FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferPointervOES)(GLenum, GLenum, void **) = nullptr; +FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferOES)(GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglUnmapBufferOES)(GLenum) = nullptr; + +/* GL_OES_texture_3D */ +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage3DOES)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage3DOES)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCopyTexSubImage3DOES)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture3DOES)(GLenum, GLenum, GLenum, GLuint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexImage3DOES)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexSubImage3DOES)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *) = nullptr; + +/* GL_OES_vertex_array_object */ +FLEXTGL_EXPORT void(APIENTRY *flextglBindVertexArrayOES)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteVertexArraysOES)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenVertexArraysOES)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsVertexArrayOES)(GLuint) = nullptr; + +#ifdef __cplusplus +} +#endif diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.cpp.template b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.cpp.template new file mode 100644 index 000000000..dfc149e94 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.cpp.template @@ -0,0 +1,22 @@ +@require(passthru, functions, enums, options, version, extensions) +#include "flextGLWindowsDesktop.h" + +#ifdef __cplusplus +extern "C" { +#endif +@for category,funcs in functions: +@if funcs: + +/* GL_@category */ +@for f in funcs: + @if f.name not in ['BlendFunc', 'Clear', 'ClearColor', 'ClearDepth', 'ClearStencil', 'ColorMask', 'CullFace', 'DepthFunc', 'DepthMask', 'DepthRange', 'Disable', 'DrawBuffer', 'Enable', 'Finish', 'Flush', 'FrontFace', 'GetBooleanv', 'GetDoublev', 'GetError', 'GetFloatv', 'GetIntegerv', 'GetString', 'GetTexImage', 'GetTexLevelParameterfv', 'GetTexLevelParameteriv', 'GetTexParameterfv', 'GetTexParameteriv', 'Hint', 'IsEnabled', 'LineWidth', 'LogicOp', 'PixelStoref', 'PixelStorei', 'PointSize', 'PolygonMode', 'ReadBuffer', 'ReadPixels', 'Scissor', 'StencilFunc', 'StencilMask', 'StencilOp', 'TexImage1D', 'TexImage2D', 'TexParameterf', 'TexParameterfv', 'TexParameteri', 'TexParameteriv', 'Viewport', 'BindTexture', 'CopyTexImage1D', 'CopyTexImage2D', 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'DeleteTextures', 'DrawArrays', 'DrawElements', 'GenTextures', 'IsTexture', 'PolygonOffset', 'TexSubImage1D', 'TexSubImage2D']: +FLEXTGL_EXPORT @f.returntype\ +(APIENTRY *flextgl@f.name)(@f.param_type_list_string()) = nullptr; + @end +@end +@end +@end + +#ifdef __cplusplus +} +#endif diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.h b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.h new file mode 100644 index 000000000..2af306248 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.h @@ -0,0 +1,1627 @@ +#ifndef _flextgl_h_ +#define _flextgl_h_ + +#include + +#include "Magnum/configure.h" + +/* Defensive include guards */ + +#if defined(__gl_h_) || defined(__gl2_h_) +#error Attempt to include auto-generated header after including gl2.h +#endif +#if defined(__gl2ext_h_) +#error Attempt to include auto-generated header after including gl2ext.h +#endif +#if defined(__gl2platform_h_) +#error Attempt to include auto-generated header after including gl2platform.h +#endif + +#define __gl_h_ +#define __gl2_h_ +#define __gl2ext_h_ +#define __gl2platform_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +void flextGLInit(); + +/* Function declaration macros */ + +#ifndef MAGNUM_BUILD_STATIC + #ifdef FlextGL_EXPORTS + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_STATIC +#endif + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define APIENTRY WINAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/* Data types */ + +#include +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef short GLshort; +typedef int GLint; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef int GLsizei; +typedef char GLchar; +typedef struct __GLsync *GLsync; +typedef void (APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef khronos_int8_t GLbyte; +typedef khronos_uint8_t GLubyte; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; + +/* Enums */ + +/* GL_ES_VERSION_2_0 */ + +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_NONE 0 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + +/* GL_ANGLE_framebuffer_blit */ + +#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA + +/* GL_ANGLE_framebuffer_multisample */ + +#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 +#define GL_MAX_SAMPLES_ANGLE 0x8D57 + +/* GL_ANGLE_instanced_arrays */ + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE + +/* GL_ANGLE_depth_texture */ + +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#define GL_DEPTH24_STENCIL8_OES 0x88F0 + +/* GL_APPLE_framebuffer_multisample */ + +#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56 +#define GL_MAX_SAMPLES_APPLE 0x8D57 +#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA + +/* GL_APPLE_texture_max_level */ + +#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D + +/* GL_EXT_texture_type_2_10_10_10_REV */ + +#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 + +/* GL_EXT_discard_framebuffer */ + +#define GL_COLOR_EXT 0x1800 +#define GL_DEPTH_EXT 0x1801 +#define GL_STENCIL_EXT 0x1802 + +/* GL_EXT_blend_minmax */ + +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 + +/* GL_EXT_unpack_subimage */ + +#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2 +#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4 + +/* GL_EXT_occlusion_query_boolean */ + +#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A +#define GL_CURRENT_QUERY_EXT 0x8865 +#define GL_QUERY_RESULT_EXT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 + +/* GL_EXT_shadow_samplers */ + +#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C +#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D +#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E +#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 + +/* GL_EXT_texture_rg */ + +#define GL_RED_EXT 0x1903 +#define GL_RG_EXT 0x8227 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B + +/* GL_EXT_sRGB */ + +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210 + +/* GL_EXT_texture_storage */ + +#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F +#define GL_ALPHA8_EXT 0x803C +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_RGBA32F_EXT 0x8814 +#define GL_RGB32F_EXT 0x8815 +#define GL_ALPHA32F_EXT 0x8816 +#define GL_LUMINANCE32F_EXT 0x8818 +#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 +#define GL_RGBA16F_EXT 0x881A +#define GL_RGB16F_EXT 0x881B +#define GL_ALPHA16F_EXT 0x881C +#define GL_LUMINANCE16F_EXT 0x881E +#define GL_LUMINANCE_ALPHA16F_EXT 0x881F +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGB10_EXT 0x8052 +#define GL_BGRA8_EXT 0x93A1 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#define GL_R32F_EXT 0x822E +#define GL_RG32F_EXT 0x8230 +#define GL_R16F_EXT 0x822D +#define GL_RG16F_EXT 0x822F + +/* GL_EXT_map_buffer_range */ + +#define GL_MAP_READ_BIT_EXT 0x0001 +#define GL_MAP_WRITE_BIT_EXT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020 + +/* GL_EXT_draw_buffers */ + +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 +#define GL_DRAW_BUFFER0_EXT 0x8825 +#define GL_DRAW_BUFFER1_EXT 0x8826 +#define GL_DRAW_BUFFER2_EXT 0x8827 +#define GL_DRAW_BUFFER3_EXT 0x8828 +#define GL_DRAW_BUFFER4_EXT 0x8829 +#define GL_DRAW_BUFFER5_EXT 0x882A +#define GL_DRAW_BUFFER6_EXT 0x882B +#define GL_DRAW_BUFFER7_EXT 0x882C +#define GL_DRAW_BUFFER8_EXT 0x882D +#define GL_DRAW_BUFFER9_EXT 0x882E +#define GL_DRAW_BUFFER10_EXT 0x882F +#define GL_DRAW_BUFFER11_EXT 0x8830 +#define GL_DRAW_BUFFER12_EXT 0x8831 +#define GL_DRAW_BUFFER13_EXT 0x8832 +#define GL_DRAW_BUFFER14_EXT 0x8833 +#define GL_DRAW_BUFFER15_EXT 0x8834 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF + +/* GL_EXT_instanced_arrays */ + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE + +/* GL_NV_draw_buffers */ + +#define GL_MAX_DRAW_BUFFERS_NV 0x8824 +#define GL_DRAW_BUFFER0_NV 0x8825 +#define GL_DRAW_BUFFER1_NV 0x8826 +#define GL_DRAW_BUFFER2_NV 0x8827 +#define GL_DRAW_BUFFER3_NV 0x8828 +#define GL_DRAW_BUFFER4_NV 0x8829 +#define GL_DRAW_BUFFER5_NV 0x882A +#define GL_DRAW_BUFFER6_NV 0x882B +#define GL_DRAW_BUFFER7_NV 0x882C +#define GL_DRAW_BUFFER8_NV 0x882D +#define GL_DRAW_BUFFER9_NV 0x882E +#define GL_DRAW_BUFFER10_NV 0x882F +#define GL_DRAW_BUFFER11_NV 0x8830 +#define GL_DRAW_BUFFER12_NV 0x8831 +#define GL_DRAW_BUFFER13_NV 0x8832 +#define GL_DRAW_BUFFER14_NV 0x8833 +#define GL_DRAW_BUFFER15_NV 0x8834 +#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 +#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 +#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 +#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 +#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 +#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 +#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 +#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 +#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 +#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 +#define GL_COLOR_ATTACHMENT10_NV 0x8CEA +#define GL_COLOR_ATTACHMENT11_NV 0x8CEB +#define GL_COLOR_ATTACHMENT12_NV 0x8CEC +#define GL_COLOR_ATTACHMENT13_NV 0x8CED +#define GL_COLOR_ATTACHMENT14_NV 0x8CEE +#define GL_COLOR_ATTACHMENT15_NV 0x8CEF + +/* GL_NV_fbo_color_attachments */ + +#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF +#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 +#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 +#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 +#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 +#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 +#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 +#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 +#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 +#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 +#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 +#define GL_COLOR_ATTACHMENT10_NV 0x8CEA +#define GL_COLOR_ATTACHMENT11_NV 0x8CEB +#define GL_COLOR_ATTACHMENT12_NV 0x8CEC +#define GL_COLOR_ATTACHMENT13_NV 0x8CED +#define GL_COLOR_ATTACHMENT14_NV 0x8CEE +#define GL_COLOR_ATTACHMENT15_NV 0x8CEF + +/* GL_NV_read_buffer */ + +#define GL_READ_BUFFER_NV 0x0C02 + +/* GL_NV_framebuffer_blit */ + +#define GL_READ_FRAMEBUFFER_NV 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA + +/* GL_NV_framebuffer_multisample */ + +#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56 +#define GL_MAX_SAMPLES_NV 0x8D57 + +/* GL_NV_instanced_arrays */ + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE + +/* GL_NV_shadow_samplers_array */ + +#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4 + +/* GL_NV_shadow_samplers_cube */ + +#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5 + +/* GL_OES_depth24 */ + +#define GL_DEPTH_COMPONENT24_OES 0x81A6 + +/* GL_OES_element_index_uint */ + +#define GL_UNSIGNED_INT 0x1405 + +/* GL_OES_rgb8_rgba8 */ + +#define GL_RGB8_OES 0x8051 +#define GL_RGBA8_OES 0x8058 + +/* GL_OES_texture_3D */ + +#define GL_TEXTURE_WRAP_R_OES 0x8072 +#define GL_TEXTURE_3D_OES 0x806F +#define GL_TEXTURE_BINDING_3D_OES 0x806A +#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 +#define GL_SAMPLER_3D_OES 0x8B5F +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 + +/* GL_OES_texture_half_float */ + +#define GL_HALF_FLOAT_OES 0x8D61 + +/* GL_OES_texture_float */ + +#define GL_FLOAT 0x1406 + +/* GL_OES_vertex_half_float */ + +#define GL_HALF_FLOAT_OES 0x8D61 + +/* GL_OES_packed_depth_stencil */ + +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH24_STENCIL8_OES 0x88F0 + +/* GL_OES_depth_texture */ + +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_INT 0x1405 + +/* GL_OES_standard_derivatives */ + +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B + +/* GL_OES_vertex_array_object */ + +#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5 + +/* GL_OES_required_internalformat */ + +#define GL_ALPHA8_OES 0x803C +#define GL_DEPTH_COMPONENT16_OES 0x81A5 +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#define GL_LUMINANCE4_ALPHA4_OES 0x8043 +#define GL_LUMINANCE8_ALPHA8_OES 0x8045 +#define GL_LUMINANCE8_OES 0x8040 +#define GL_RGBA4_OES 0x8056 +#define GL_RGB5_A1_OES 0x8057 +#define GL_RGB565_OES 0x8D62 +#define GL_RGB8_OES 0x8051 +#define GL_RGBA8_OES 0x8058 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB10_A2_EXT 0x8059 + +/* GL_OES_surfaceless_context */ + +#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219 + +/* GL_APPLE_texture_format_BGRA8888 */ + +#define GL_BGRA_EXT 0x80E1 +#define GL_BGRA8_EXT 0x93A1 + +/* GL_ARM_shader_framebuffer_fetch */ + +#define GL_FETCH_PER_SAMPLE_ARM 0x8F65 +#define GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66 + +/* GL_EXT_texture_filter_anisotropic */ + +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + +/* GL_EXT_texture_format_BGRA8888 */ + +#define GL_BGRA_EXT 0x80E1 + +/* GL_EXT_read_format_bgra */ + +#define GL_BGRA_EXT 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 + +/* GL_EXT_debug_label */ + +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 +#define GL_SAMPLER 0x82E6 +#define GL_TRANSFORM_FEEDBACK 0x8E22 + +/* GL_EXT_shader_framebuffer_fetch */ + +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 + +/* GL_EXT_disjoint_timer_query */ + +#define GL_QUERY_COUNTER_BITS_EXT 0x8864 +#define GL_CURRENT_QUERY_EXT 0x8865 +#define GL_QUERY_RESULT_EXT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 +#define GL_TIME_ELAPSED_EXT 0x88BF +#define GL_TIMESTAMP_EXT 0x8E28 +#define GL_GPU_DISJOINT_EXT 0x8FBB + +/* GL_EXT_texture_sRGB_decode */ + +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A + +/* GL_EXT_sRGB_write_control */ + +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 + +/* GL_EXT_texture_compression_s3tc */ + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +/* GL_EXT_draw_buffers_indexed */ + +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_BLEND 0x0BE2 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_SRC_ALPHA_SATURATE 0x0308 + +/* GL_EXT_texture_border_clamp */ + +#define GL_TEXTURE_BORDER_COLOR_EXT 0x1004 +#define GL_CLAMP_TO_BORDER_EXT 0x812D + +/* GL_EXT_separate_shader_objects */ + +#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 +#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE_EXT 0x8258 +#define GL_ACTIVE_PROGRAM_EXT 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A + +/* GL_EXT_multisampled_render_to_texture */ + +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 + +/* GL_EXT_robustness */ + +#define GL_NO_ERROR 0 +#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 +#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 +#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 +#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 +#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 + +/* GL_KHR_texture_compression_astc_ldr */ + +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD + +/* GL_KHR_texture_compression_astc_hdr */ + +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD + +/* GL_KHR_debug */ + +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245 +#define GL_DEBUG_SOURCE_API_KHR 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A +#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B +#define GL_DEBUG_TYPE_ERROR_KHR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250 +#define GL_DEBUG_TYPE_OTHER_KHR 0x8251 +#define GL_DEBUG_TYPE_MARKER_KHR 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D +#define GL_BUFFER_KHR 0x82E0 +#define GL_SHADER_KHR 0x82E1 +#define GL_PROGRAM_KHR 0x82E2 +#define GL_VERTEX_ARRAY_KHR 0x8074 +#define GL_QUERY_KHR 0x82E3 +#define GL_PROGRAM_PIPELINE_KHR 0x82E4 +#define GL_SAMPLER_KHR 0x82E6 +#define GL_MAX_LABEL_LENGTH_KHR 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147 +#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148 +#define GL_DEBUG_OUTPUT_KHR 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002 +#define GL_STACK_OVERFLOW_KHR 0x0503 +#define GL_STACK_UNDERFLOW_KHR 0x0504 + +/* GL_KHR_blend_equation_advanced */ + +#define GL_MULTIPLY_KHR 0x9294 +#define GL_SCREEN_KHR 0x9295 +#define GL_OVERLAY_KHR 0x9296 +#define GL_DARKEN_KHR 0x9297 +#define GL_LIGHTEN_KHR 0x9298 +#define GL_COLORDODGE_KHR 0x9299 +#define GL_COLORBURN_KHR 0x929A +#define GL_HARDLIGHT_KHR 0x929B +#define GL_SOFTLIGHT_KHR 0x929C +#define GL_DIFFERENCE_KHR 0x929E +#define GL_EXCLUSION_KHR 0x92A0 +#define GL_HSL_HUE_KHR 0x92AD +#define GL_HSL_SATURATION_KHR 0x92AE +#define GL_HSL_COLOR_KHR 0x92AF +#define GL_HSL_LUMINOSITY_KHR 0x92B0 + +/* GL_KHR_blend_equation_advanced_coherent */ + +#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285 + +/* GL_KHR_robustness */ + +#define GL_NO_ERROR 0 +#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3 +#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252 +#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256 +#define GL_NO_RESET_NOTIFICATION_KHR 0x8261 +#define GL_CONTEXT_LOST_KHR 0x0507 + +/* GL_KHR_context_flush_control */ + +#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC +#define GL_NONE 0 + +/* GL_KHR_no_error */ + +#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008 + +/* GL_NV_texture_border_clamp */ + +#define GL_TEXTURE_BORDER_COLOR_NV 0x1004 +#define GL_CLAMP_TO_BORDER_NV 0x812D + +/* GL_NV_polygon_mode */ + +#define GL_POLYGON_MODE_NV 0x0B40 +#define GL_POLYGON_OFFSET_POINT_NV 0x2A01 +#define GL_POLYGON_OFFSET_LINE_NV 0x2A02 +#define GL_POINT_NV 0x1B00 +#define GL_LINE_NV 0x1B01 +#define GL_FILL_NV 0x1B02 + +/* GL_OES_depth32 */ + +#define GL_DEPTH_COMPONENT32_OES 0x81A7 + +/* GL_OES_mapbuffer */ + +#define GL_WRITE_ONLY_OES 0x88B9 +#define GL_BUFFER_ACCESS_OES 0x88BB +#define GL_BUFFER_MAPPED_OES 0x88BC +#define GL_BUFFER_MAP_POINTER_OES 0x88BD + +/* GL_OES_stencil1 */ + +#define GL_STENCIL_INDEX1_OES 0x8D46 + +/* GL_OES_stencil4 */ + +#define GL_STENCIL_INDEX4_OES 0x8D47 + +/* GL_OES_texture_stencil8 */ + +#define GL_STENCIL_INDEX_OES 0x1901 +#define GL_STENCIL_INDEX8_OES 0x8D48 + +/* Function prototypes */ + +/* GL_ANGLE_framebuffer_blit */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlitFramebufferANGLE)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); +#define glBlitFramebufferANGLE flextglBlitFramebufferANGLE + +/* GL_ANGLE_framebuffer_multisample */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleANGLE)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorageMultisampleANGLE flextglRenderbufferStorageMultisampleANGLE + +/* GL_ANGLE_instanced_arrays */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstancedANGLE)(GLenum, GLint, GLsizei, GLsizei); +#define glDrawArraysInstancedANGLE flextglDrawArraysInstancedANGLE +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstancedANGLE)(GLenum, GLsizei, GLenum, const void *, GLsizei); +#define glDrawElementsInstancedANGLE flextglDrawElementsInstancedANGLE +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisorANGLE)(GLuint, GLuint); +#define glVertexAttribDivisorANGLE flextglVertexAttribDivisorANGLE + +/* GL_APPLE_framebuffer_multisample */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleAPPLE)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorageMultisampleAPPLE flextglRenderbufferStorageMultisampleAPPLE +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglResolveMultisampleFramebufferAPPLE)(void); +#define glResolveMultisampleFramebufferAPPLE flextglResolveMultisampleFramebufferAPPLE + +/* GL_ES_VERSION_2_0 */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglActiveTexture)(GLenum); +#define glActiveTexture flextglActiveTexture +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglAttachShader)(GLuint, GLuint); +#define glAttachShader flextglAttachShader +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindAttribLocation)(GLuint, GLuint, const GLchar *); +#define glBindAttribLocation flextglBindAttribLocation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindBuffer)(GLenum, GLuint); +#define glBindBuffer flextglBindBuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindFramebuffer)(GLenum, GLuint); +#define glBindFramebuffer flextglBindFramebuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindRenderbuffer)(GLenum, GLuint); +#define glBindRenderbuffer flextglBindRenderbuffer +GLAPI FLEXTGL_EXPORT void APIENTRY glBindTexture(GLenum, GLuint); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendColor)(GLfloat, GLfloat, GLfloat, GLfloat); +#define glBlendColor flextglBlendColor +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquation)(GLenum); +#define glBlendEquation flextglBlendEquation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparate)(GLenum, GLenum); +#define glBlendEquationSeparate flextglBlendEquationSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glBlendFunc(GLenum, GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparate)(GLenum, GLenum, GLenum, GLenum); +#define glBlendFuncSeparate flextglBlendFuncSeparate +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBufferData)(GLenum, GLsizeiptr, const void *, GLenum); +#define glBufferData flextglBufferData +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBufferSubData)(GLenum, GLintptr, GLsizeiptr, const void *); +#define glBufferSubData flextglBufferSubData +GLAPI FLEXTGL_EXPORT GLenum(APIENTRY *flextglCheckFramebufferStatus)(GLenum); +#define glCheckFramebufferStatus flextglCheckFramebufferStatus +GLAPI FLEXTGL_EXPORT void APIENTRY glClear(GLbitfield); +GLAPI FLEXTGL_EXPORT void APIENTRY glClearColor(GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglClearDepthf)(GLfloat); +#define glClearDepthf flextglClearDepthf +GLAPI FLEXTGL_EXPORT void APIENTRY glClearStencil(GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glColorMask(GLboolean, GLboolean, GLboolean, GLboolean); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompileShader)(GLuint); +#define glCompileShader flextglCompileShader +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage2D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *); +#define glCompressedTexImage2D flextglCompressedTexImage2D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *); +#define glCompressedTexSubImage2D flextglCompressedTexSubImage2D +GLAPI FLEXTGL_EXPORT void APIENTRY glCopyTexImage2D(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glCopyTexSubImage2D(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateProgram)(void); +#define glCreateProgram flextglCreateProgram +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShader)(GLenum); +#define glCreateShader flextglCreateShader +GLAPI FLEXTGL_EXPORT void APIENTRY glCullFace(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteBuffers)(GLsizei, const GLuint *); +#define glDeleteBuffers flextglDeleteBuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteFramebuffers)(GLsizei, const GLuint *); +#define glDeleteFramebuffers flextglDeleteFramebuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgram)(GLuint); +#define glDeleteProgram flextglDeleteProgram +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteRenderbuffers)(GLsizei, const GLuint *); +#define glDeleteRenderbuffers flextglDeleteRenderbuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteShader)(GLuint); +#define glDeleteShader flextglDeleteShader +GLAPI FLEXTGL_EXPORT void APIENTRY glDeleteTextures(GLsizei, const GLuint *); +GLAPI FLEXTGL_EXPORT void APIENTRY glDepthFunc(GLenum); +GLAPI FLEXTGL_EXPORT void APIENTRY glDepthMask(GLboolean); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDepthRangef)(GLfloat, GLfloat); +#define glDepthRangef flextglDepthRangef +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDetachShader)(GLuint, GLuint); +#define glDetachShader flextglDetachShader +GLAPI FLEXTGL_EXPORT void APIENTRY glDisable(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDisableVertexAttribArray)(GLuint); +#define glDisableVertexAttribArray flextglDisableVertexAttribArray +GLAPI FLEXTGL_EXPORT void APIENTRY glDrawArrays(GLenum, GLint, GLsizei); +GLAPI FLEXTGL_EXPORT void APIENTRY glDrawElements(GLenum, GLsizei, GLenum, const void *); +GLAPI FLEXTGL_EXPORT void APIENTRY glEnable(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEnableVertexAttribArray)(GLuint); +#define glEnableVertexAttribArray flextglEnableVertexAttribArray +GLAPI FLEXTGL_EXPORT void APIENTRY glFinish(void); +GLAPI FLEXTGL_EXPORT void APIENTRY glFlush(void); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint); +#define glFramebufferRenderbuffer flextglFramebufferRenderbuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint, GLint); +#define glFramebufferTexture2D flextglFramebufferTexture2D +GLAPI FLEXTGL_EXPORT void APIENTRY glFrontFace(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenBuffers)(GLsizei, GLuint *); +#define glGenBuffers flextglGenBuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenFramebuffers)(GLsizei, GLuint *); +#define glGenFramebuffers flextglGenFramebuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenRenderbuffers)(GLsizei, GLuint *); +#define glGenRenderbuffers flextglGenRenderbuffers +GLAPI FLEXTGL_EXPORT void APIENTRY glGenTextures(GLsizei, GLuint *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenerateMipmap)(GLenum); +#define glGenerateMipmap flextglGenerateMipmap +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveAttrib)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +#define glGetActiveAttrib flextglGetActiveAttrib +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniform)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +#define glGetActiveUniform flextglGetActiveUniform +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetAttachedShaders)(GLuint, GLsizei, GLsizei *, GLuint *); +#define glGetAttachedShaders flextglGetAttachedShaders +GLAPI FLEXTGL_EXPORT GLint(APIENTRY *flextglGetAttribLocation)(GLuint, const GLchar *); +#define glGetAttribLocation flextglGetAttribLocation +GLAPI FLEXTGL_EXPORT void APIENTRY glGetBooleanv(GLenum, GLboolean *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferParameteriv)(GLenum, GLenum, GLint *); +#define glGetBufferParameteriv flextglGetBufferParameteriv +GLAPI FLEXTGL_EXPORT GLenum APIENTRY glGetError(void); +GLAPI FLEXTGL_EXPORT void APIENTRY glGetFloatv(GLenum, GLfloat *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetFramebufferAttachmentParameteriv)(GLenum, GLenum, GLenum, GLint *); +#define glGetFramebufferAttachmentParameteriv flextglGetFramebufferAttachmentParameteriv +GLAPI FLEXTGL_EXPORT void APIENTRY glGetIntegerv(GLenum, GLint *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetProgramInfoLog flextglGetProgramInfoLog +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramiv)(GLuint, GLenum, GLint *); +#define glGetProgramiv flextglGetProgramiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetRenderbufferParameteriv)(GLenum, GLenum, GLint *); +#define glGetRenderbufferParameteriv flextglGetRenderbufferParameteriv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetShaderInfoLog flextglGetShaderInfoLog +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderPrecisionFormat)(GLenum, GLenum, GLint *, GLint *); +#define glGetShaderPrecisionFormat flextglGetShaderPrecisionFormat +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderSource)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetShaderSource flextglGetShaderSource +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderiv)(GLuint, GLenum, GLint *); +#define glGetShaderiv flextglGetShaderiv +GLAPI FLEXTGL_EXPORT const GLubyte * APIENTRY glGetString(GLenum); +GLAPI FLEXTGL_EXPORT void APIENTRY glGetTexParameterfv(GLenum, GLenum, GLfloat *); +GLAPI FLEXTGL_EXPORT void APIENTRY glGetTexParameteriv(GLenum, GLenum, GLint *); +GLAPI FLEXTGL_EXPORT GLint(APIENTRY *flextglGetUniformLocation)(GLuint, const GLchar *); +#define glGetUniformLocation flextglGetUniformLocation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformfv)(GLuint, GLint, GLfloat *); +#define glGetUniformfv flextglGetUniformfv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformiv)(GLuint, GLint, GLint *); +#define glGetUniformiv flextglGetUniformiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribPointerv)(GLuint, GLenum, void **); +#define glGetVertexAttribPointerv flextglGetVertexAttribPointerv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribfv)(GLuint, GLenum, GLfloat *); +#define glGetVertexAttribfv flextglGetVertexAttribfv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribiv)(GLuint, GLenum, GLint *); +#define glGetVertexAttribiv flextglGetVertexAttribiv +GLAPI FLEXTGL_EXPORT void APIENTRY glHint(GLenum, GLenum); +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsBuffer)(GLuint); +#define glIsBuffer flextglIsBuffer +GLAPI FLEXTGL_EXPORT GLboolean APIENTRY glIsEnabled(GLenum); +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsFramebuffer)(GLuint); +#define glIsFramebuffer flextglIsFramebuffer +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgram)(GLuint); +#define glIsProgram flextglIsProgram +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsRenderbuffer)(GLuint); +#define glIsRenderbuffer flextglIsRenderbuffer +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsShader)(GLuint); +#define glIsShader flextglIsShader +GLAPI FLEXTGL_EXPORT GLboolean APIENTRY glIsTexture(GLuint); +GLAPI FLEXTGL_EXPORT void APIENTRY glLineWidth(GLfloat); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglLinkProgram)(GLuint); +#define glLinkProgram flextglLinkProgram +GLAPI FLEXTGL_EXPORT void APIENTRY glPixelStorei(GLenum, GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glPolygonOffset(GLfloat, GLfloat); +GLAPI FLEXTGL_EXPORT void APIENTRY glReadPixels(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, void *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglReleaseShaderCompiler)(void); +#define glReleaseShaderCompiler flextglReleaseShaderCompiler +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorage flextglRenderbufferStorage +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSampleCoverage)(GLfloat, GLboolean); +#define glSampleCoverage flextglSampleCoverage +GLAPI FLEXTGL_EXPORT void APIENTRY glScissor(GLint, GLint, GLsizei, GLsizei); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglShaderBinary)(GLsizei, const GLuint *, GLenum, const void *, GLsizei); +#define glShaderBinary flextglShaderBinary +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglShaderSource)(GLuint, GLsizei, const GLchar *const*, const GLint *); +#define glShaderSource flextglShaderSource +GLAPI FLEXTGL_EXPORT void APIENTRY glStencilFunc(GLenum, GLint, GLuint); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint); +#define glStencilFuncSeparate flextglStencilFuncSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glStencilMask(GLuint); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglStencilMaskSeparate)(GLenum, GLuint); +#define glStencilMaskSeparate flextglStencilMaskSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glStencilOp(GLenum, GLenum, GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum); +#define glStencilOpSeparate flextglStencilOpSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glTexImage2D(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameterf(GLenum, GLenum, GLfloat); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameterfv(GLenum, GLenum, const GLfloat *); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameteri(GLenum, GLenum, GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameteriv(GLenum, GLenum, const GLint *); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexSubImage2D(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1f)(GLint, GLfloat); +#define glUniform1f flextglUniform1f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1fv)(GLint, GLsizei, const GLfloat *); +#define glUniform1fv flextglUniform1fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1i)(GLint, GLint); +#define glUniform1i flextglUniform1i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1iv)(GLint, GLsizei, const GLint *); +#define glUniform1iv flextglUniform1iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2f)(GLint, GLfloat, GLfloat); +#define glUniform2f flextglUniform2f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2fv)(GLint, GLsizei, const GLfloat *); +#define glUniform2fv flextglUniform2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2i)(GLint, GLint, GLint); +#define glUniform2i flextglUniform2i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2iv)(GLint, GLsizei, const GLint *); +#define glUniform2iv flextglUniform2iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3f)(GLint, GLfloat, GLfloat, GLfloat); +#define glUniform3f flextglUniform3f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3fv)(GLint, GLsizei, const GLfloat *); +#define glUniform3fv flextglUniform3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3i)(GLint, GLint, GLint, GLint); +#define glUniform3i flextglUniform3i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3iv)(GLint, GLsizei, const GLint *); +#define glUniform3iv flextglUniform3iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat); +#define glUniform4f flextglUniform4f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4fv)(GLint, GLsizei, const GLfloat *); +#define glUniform4fv flextglUniform4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4i)(GLint, GLint, GLint, GLint, GLint); +#define glUniform4i flextglUniform4i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4iv)(GLint, GLsizei, const GLint *); +#define glUniform4iv flextglUniform4iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix2fv flextglUniformMatrix2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix3fv flextglUniformMatrix3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix4fv flextglUniformMatrix4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUseProgram)(GLuint); +#define glUseProgram flextglUseProgram +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgram)(GLuint); +#define glValidateProgram flextglValidateProgram +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1f)(GLuint, GLfloat); +#define glVertexAttrib1f flextglVertexAttrib1f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1fv)(GLuint, const GLfloat *); +#define glVertexAttrib1fv flextglVertexAttrib1fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2f)(GLuint, GLfloat, GLfloat); +#define glVertexAttrib2f flextglVertexAttrib2f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2fv)(GLuint, const GLfloat *); +#define glVertexAttrib2fv flextglVertexAttrib2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3f)(GLuint, GLfloat, GLfloat, GLfloat); +#define glVertexAttrib3f flextglVertexAttrib3f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3fv)(GLuint, const GLfloat *); +#define glVertexAttrib3fv flextglVertexAttrib3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4f)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +#define glVertexAttrib4f flextglVertexAttrib4f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4fv)(GLuint, const GLfloat *); +#define glVertexAttrib4fv flextglVertexAttrib4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *); +#define glVertexAttribPointer flextglVertexAttribPointer +GLAPI FLEXTGL_EXPORT void APIENTRY glViewport(GLint, GLint, GLsizei, GLsizei); + +/* GL_EXT_debug_label */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelEXT)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetObjectLabelEXT flextglGetObjectLabelEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglLabelObjectEXT)(GLenum, GLuint, GLsizei, const GLchar *); +#define glLabelObjectEXT flextglLabelObjectEXT + +/* GL_EXT_debug_marker */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglInsertEventMarkerEXT)(GLsizei, const GLchar *); +#define glInsertEventMarkerEXT flextglInsertEventMarkerEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPopGroupMarkerEXT)(void); +#define glPopGroupMarkerEXT flextglPopGroupMarkerEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPushGroupMarkerEXT)(GLsizei, const GLchar *); +#define glPushGroupMarkerEXT flextglPushGroupMarkerEXT + +/* GL_EXT_discard_framebuffer */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDiscardFramebufferEXT)(GLenum, GLsizei, const GLenum *); +#define glDiscardFramebufferEXT flextglDiscardFramebufferEXT + +/* GL_EXT_disjoint_timer_query */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjecti64vEXT)(GLuint, GLenum, GLint64 *); +#define glGetQueryObjecti64vEXT flextglGetQueryObjecti64vEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectivEXT)(GLuint, GLenum, GLint *); +#define glGetQueryObjectivEXT flextglGetQueryObjectivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectui64vEXT)(GLuint, GLenum, GLuint64 *); +#define glGetQueryObjectui64vEXT flextglGetQueryObjectui64vEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglQueryCounterEXT)(GLuint, GLenum); +#define glQueryCounterEXT flextglQueryCounterEXT + +/* GL_EXT_draw_buffers */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawBuffersEXT)(GLsizei, const GLenum *); +#define glDrawBuffersEXT flextglDrawBuffersEXT + +/* GL_EXT_draw_buffers_indexed */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparateiEXT)(GLuint, GLenum, GLenum); +#define glBlendEquationSeparateiEXT flextglBlendEquationSeparateiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationiEXT)(GLuint, GLenum); +#define glBlendEquationiEXT flextglBlendEquationiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparateiEXT)(GLuint, GLenum, GLenum, GLenum, GLenum); +#define glBlendFuncSeparateiEXT flextglBlendFuncSeparateiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendFunciEXT)(GLuint, GLenum, GLenum); +#define glBlendFunciEXT flextglBlendFunciEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglColorMaskiEXT)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +#define glColorMaskiEXT flextglColorMaskiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDisableiEXT)(GLenum, GLuint); +#define glDisableiEXT flextglDisableiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEnableiEXT)(GLenum, GLuint); +#define glEnableiEXT flextglEnableiEXT +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsEnablediEXT)(GLenum, GLuint); +#define glIsEnablediEXT flextglIsEnablediEXT + +/* GL_EXT_instanced_arrays */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstancedEXT)(GLenum, GLint, GLsizei, GLsizei); +#define glDrawArraysInstancedEXT flextglDrawArraysInstancedEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstancedEXT)(GLenum, GLsizei, GLenum, const void *, GLsizei); +#define glDrawElementsInstancedEXT flextglDrawElementsInstancedEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisorEXT)(GLuint, GLuint); +#define glVertexAttribDivisorEXT flextglVertexAttribDivisorEXT + +/* GL_EXT_map_buffer_range */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFlushMappedBufferRangeEXT)(GLenum, GLintptr, GLsizeiptr); +#define glFlushMappedBufferRangeEXT flextglFlushMappedBufferRangeEXT +GLAPI FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferRangeEXT)(GLenum, GLintptr, GLsizeiptr, GLbitfield); +#define glMapBufferRangeEXT flextglMapBufferRangeEXT + +/* GL_EXT_multi_draw_arrays */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawArraysEXT)(GLenum, const GLint *, const GLsizei *, GLsizei); +#define glMultiDrawArraysEXT flextglMultiDrawArraysEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawElementsEXT)(GLenum, const GLsizei *, GLenum, const void *const*, GLsizei); +#define glMultiDrawElementsEXT flextglMultiDrawElementsEXT + +/* GL_EXT_multisampled_render_to_texture */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2DMultisampleEXT)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); +#define glFramebufferTexture2DMultisampleEXT flextglFramebufferTexture2DMultisampleEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorageMultisampleEXT flextglRenderbufferStorageMultisampleEXT + +/* GL_EXT_occlusion_query_boolean */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBeginQueryEXT)(GLenum, GLuint); +#define glBeginQueryEXT flextglBeginQueryEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteQueriesEXT)(GLsizei, const GLuint *); +#define glDeleteQueriesEXT flextglDeleteQueriesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEndQueryEXT)(GLenum); +#define glEndQueryEXT flextglEndQueryEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenQueriesEXT)(GLsizei, GLuint *); +#define glGenQueriesEXT flextglGenQueriesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectuivEXT)(GLuint, GLenum, GLuint *); +#define glGetQueryObjectuivEXT flextglGetQueryObjectuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryivEXT)(GLenum, GLenum, GLint *); +#define glGetQueryivEXT flextglGetQueryivEXT +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsQueryEXT)(GLuint); +#define glIsQueryEXT flextglIsQueryEXT + +/* GL_EXT_robustness */ + +GLAPI FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusEXT)(void); +#define glGetGraphicsResetStatusEXT flextglGetGraphicsResetStatusEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvEXT)(GLuint, GLint, GLsizei, GLfloat *); +#define glGetnUniformfvEXT flextglGetnUniformfvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivEXT)(GLuint, GLint, GLsizei, GLint *); +#define glGetnUniformivEXT flextglGetnUniformivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsEXT)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *); +#define glReadnPixelsEXT flextglReadnPixelsEXT + +/* GL_EXT_separate_shader_objects */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglActiveShaderProgramEXT)(GLuint, GLuint); +#define glActiveShaderProgramEXT flextglActiveShaderProgramEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindProgramPipelineEXT)(GLuint); +#define glBindProgramPipelineEXT flextglBindProgramPipelineEXT +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShaderProgramvEXT)(GLenum, GLsizei, const GLchar **); +#define glCreateShaderProgramvEXT flextglCreateShaderProgramvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgramPipelinesEXT)(GLsizei, const GLuint *); +#define glDeleteProgramPipelinesEXT flextglDeleteProgramPipelinesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenProgramPipelinesEXT)(GLsizei, GLuint *); +#define glGenProgramPipelinesEXT flextglGenProgramPipelinesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineInfoLogEXT)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetProgramPipelineInfoLogEXT flextglGetProgramPipelineInfoLogEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineivEXT)(GLuint, GLenum, GLint *); +#define glGetProgramPipelineivEXT flextglGetProgramPipelineivEXT +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgramPipelineEXT)(GLuint); +#define glIsProgramPipelineEXT flextglIsProgramPipelineEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramParameteriEXT)(GLuint, GLenum, GLint); +#define glProgramParameteriEXT flextglProgramParameteriEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fEXT)(GLuint, GLint, GLfloat); +#define glProgramUniform1fEXT flextglProgramUniform1fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform1fvEXT flextglProgramUniform1fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iEXT)(GLuint, GLint, GLint); +#define glProgramUniform1iEXT flextglProgramUniform1iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform1ivEXT flextglProgramUniform1ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fEXT)(GLuint, GLint, GLfloat, GLfloat); +#define glProgramUniform2fEXT flextglProgramUniform2fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform2fvEXT flextglProgramUniform2fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iEXT)(GLuint, GLint, GLint, GLint); +#define glProgramUniform2iEXT flextglProgramUniform2iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform2ivEXT flextglProgramUniform2ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat); +#define glProgramUniform3fEXT flextglProgramUniform3fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform3fvEXT flextglProgramUniform3fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iEXT)(GLuint, GLint, GLint, GLint, GLint); +#define glProgramUniform3iEXT flextglProgramUniform3iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform3ivEXT flextglProgramUniform3ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat); +#define glProgramUniform4fEXT flextglProgramUniform4fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform4fvEXT flextglProgramUniform4fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iEXT)(GLuint, GLint, GLint, GLint, GLint, GLint); +#define glProgramUniform4iEXT flextglProgramUniform4iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform4ivEXT flextglProgramUniform4ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix2fvEXT flextglProgramUniformMatrix2fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix3fvEXT flextglProgramUniformMatrix3fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix4fvEXT flextglProgramUniformMatrix4fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStagesEXT)(GLuint, GLbitfield, GLuint); +#define glUseProgramStagesEXT flextglUseProgramStagesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipelineEXT)(GLuint); +#define glValidateProgramPipelineEXT flextglValidateProgramPipelineEXT + +/* GL_EXT_texture_border_clamp */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIivEXT)(GLuint, GLenum, GLint *); +#define glGetSamplerParameterIivEXT flextglGetSamplerParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIuivEXT)(GLuint, GLenum, GLuint *); +#define glGetSamplerParameterIuivEXT flextglGetSamplerParameterIuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIivEXT)(GLenum, GLenum, GLint *); +#define glGetTexParameterIivEXT flextglGetTexParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIuivEXT)(GLenum, GLenum, GLuint *); +#define glGetTexParameterIuivEXT flextglGetTexParameterIuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIivEXT)(GLuint, GLenum, const GLint *); +#define glSamplerParameterIivEXT flextglSamplerParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIuivEXT)(GLuint, GLenum, const GLuint *); +#define glSamplerParameterIuivEXT flextglSamplerParameterIuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIivEXT)(GLenum, GLenum, const GLint *); +#define glTexParameterIivEXT flextglTexParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIuivEXT)(GLenum, GLenum, const GLuint *); +#define glTexParameterIuivEXT flextglTexParameterIuivEXT + +/* GL_EXT_texture_storage */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glTexStorage2DEXT flextglTexStorage2DEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3DEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei); +#define glTexStorage3DEXT flextglTexStorage3DEXT + +/* GL_KHR_blend_equation_advanced */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendBarrierKHR)(void); +#define glBlendBarrierKHR flextglBlendBarrierKHR + +/* GL_KHR_debug */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageCallbackKHR)(GLDEBUGPROCKHR, const void *); +#define glDebugMessageCallbackKHR flextglDebugMessageCallbackKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageControlKHR)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean); +#define glDebugMessageControlKHR flextglDebugMessageControlKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageInsertKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *); +#define glDebugMessageInsertKHR flextglDebugMessageInsertKHR +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetDebugMessageLogKHR)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *); +#define glGetDebugMessageLogKHR flextglGetDebugMessageLogKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelKHR)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetObjectLabelKHR flextglGetObjectLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectPtrLabelKHR)(const void *, GLsizei, GLsizei *, GLchar *); +#define glGetObjectPtrLabelKHR flextglGetObjectPtrLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetPointervKHR)(GLenum, void **); +#define glGetPointervKHR flextglGetPointervKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglObjectLabelKHR)(GLenum, GLuint, GLsizei, const GLchar *); +#define glObjectLabelKHR flextglObjectLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglObjectPtrLabelKHR)(const void *, GLsizei, const GLchar *); +#define glObjectPtrLabelKHR flextglObjectPtrLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPopDebugGroupKHR)(void); +#define glPopDebugGroupKHR flextglPopDebugGroupKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPushDebugGroupKHR)(GLenum, GLuint, GLsizei, const GLchar *); +#define glPushDebugGroupKHR flextglPushDebugGroupKHR + +/* GL_KHR_robustness */ + +GLAPI FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusKHR)(void); +#define glGetGraphicsResetStatusKHR flextglGetGraphicsResetStatusKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvKHR)(GLuint, GLint, GLsizei, GLfloat *); +#define glGetnUniformfvKHR flextglGetnUniformfvKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivKHR)(GLuint, GLint, GLsizei, GLint *); +#define glGetnUniformivKHR flextglGetnUniformivKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformuivKHR)(GLuint, GLint, GLsizei, GLuint *); +#define glGetnUniformuivKHR flextglGetnUniformuivKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsKHR)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *); +#define glReadnPixelsKHR flextglReadnPixelsKHR + +/* GL_NV_draw_buffers */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawBuffersNV)(GLsizei, const GLenum *); +#define glDrawBuffersNV flextglDrawBuffersNV + +/* GL_NV_draw_instanced */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstancedNV)(GLenum, GLint, GLsizei, GLsizei); +#define glDrawArraysInstancedNV flextglDrawArraysInstancedNV +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstancedNV)(GLenum, GLsizei, GLenum, const void *, GLsizei); +#define glDrawElementsInstancedNV flextglDrawElementsInstancedNV + +/* GL_NV_framebuffer_blit */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlitFramebufferNV)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); +#define glBlitFramebufferNV flextglBlitFramebufferNV + +/* GL_NV_framebuffer_multisample */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleNV)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorageMultisampleNV flextglRenderbufferStorageMultisampleNV + +/* GL_NV_instanced_arrays */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisorNV)(GLuint, GLuint); +#define glVertexAttribDivisorNV flextglVertexAttribDivisorNV + +/* GL_NV_polygon_mode */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPolygonModeNV)(GLenum, GLenum); +#define glPolygonModeNV flextglPolygonModeNV + +/* GL_NV_read_buffer */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglReadBufferNV)(GLenum); +#define glReadBufferNV flextglReadBufferNV + +/* GL_OES_mapbuffer */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferPointervOES)(GLenum, GLenum, void **); +#define glGetBufferPointervOES flextglGetBufferPointervOES +GLAPI FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferOES)(GLenum, GLenum); +#define glMapBufferOES flextglMapBufferOES +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglUnmapBufferOES)(GLenum); +#define glUnmapBufferOES flextglUnmapBufferOES + +/* GL_OES_texture_3D */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage3DOES)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const void *); +#define glCompressedTexImage3DOES flextglCompressedTexImage3DOES +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage3DOES)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *); +#define glCompressedTexSubImage3DOES flextglCompressedTexSubImage3DOES +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCopyTexSubImage3DOES)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#define glCopyTexSubImage3DOES flextglCopyTexSubImage3DOES +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture3DOES)(GLenum, GLenum, GLenum, GLuint, GLint, GLint); +#define glFramebufferTexture3DOES flextglFramebufferTexture3DOES +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexImage3DOES)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *); +#define glTexImage3DOES flextglTexImage3DOES +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexSubImage3DOES)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *); +#define glTexSubImage3DOES flextglTexSubImage3DOES + +/* GL_OES_vertex_array_object */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindVertexArrayOES)(GLuint); +#define glBindVertexArrayOES flextglBindVertexArrayOES +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteVertexArraysOES)(GLsizei, const GLuint *); +#define glDeleteVertexArraysOES flextglDeleteVertexArraysOES +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenVertexArraysOES)(GLsizei, GLuint *); +#define glGenVertexArraysOES flextglGenVertexArraysOES +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsVertexArrayOES)(GLuint); +#define glIsVertexArrayOES flextglIsVertexArrayOES + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.h.template b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.h.template new file mode 100644 index 000000000..b51dafe52 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLWindowsDesktop.h.template @@ -0,0 +1,90 @@ +@require(passthru, functions, enums, options, version, extensions) +#ifndef _flextgl_h_ +#define _flextgl_h_ + +#include + +#include "Magnum/configure.h" + +/* Defensive include guards */ + +#if defined(__gl_h_) || defined(__gl2_h_) +#error Attempt to include auto-generated header after including gl2.h +#endif +#if defined(__gl2ext_h_) +#error Attempt to include auto-generated header after including gl2ext.h +#endif +#if defined(__gl2platform_h_) +#error Attempt to include auto-generated header after including gl2platform.h +#endif + +#define __gl_h_ +#define __gl2_h_ +#define __gl2ext_h_ +#define __gl2platform_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +void flextGLInit(); + +/* Function declaration macros */ + +#ifndef MAGNUM_BUILD_STATIC + #ifdef FlextGL_EXPORTS + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_STATIC +#endif + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define APIENTRY WINAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/* Data types */ + +@passthru + +/* Enums */ + +@enums + +/* Function prototypes */ +@for cat,funcs in functions: +@if funcs: + +/* GL_@cat */ + + @for f in funcs: + @if f.name in ['BlendFunc', 'Clear', 'ClearColor', 'ClearDepth', 'ClearStencil', 'ColorMask', 'CullFace', 'DepthFunc', 'DepthMask', 'DepthRange', 'Disable', 'DrawBuffer', 'Enable', 'Finish', 'Flush', 'FrontFace', 'GetBooleanv', 'GetDoublev', 'GetError', 'GetFloatv', 'GetIntegerv', 'GetString', 'GetTexImage', 'GetTexLevelParameterfv', 'GetTexLevelParameteriv', 'GetTexParameterfv', 'GetTexParameteriv', 'Hint', 'IsEnabled', 'LineWidth', 'LogicOp', 'PixelStoref', 'PixelStorei', 'PointSize', 'PolygonMode', 'ReadBuffer', 'ReadPixels', 'Scissor', 'StencilFunc', 'StencilMask', 'StencilOp', 'TexImage1D', 'TexImage2D', 'TexParameterf', 'TexParameterfv', 'TexParameteri', 'TexParameteriv', 'Viewport', 'BindTexture', 'CopyTexImage1D', 'CopyTexImage2D', 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'DeleteTextures', 'DrawArrays', 'DrawElements', 'GenTextures', 'IsTexture', 'PolygonOffset', 'TexSubImage1D', 'TexSubImage2D']: +GLAPI FLEXTGL_EXPORT @f.returntype APIENTRY gl@f.name\ +(@f.param_type_list_string()); + @else: +GLAPI FLEXTGL_EXPORT @f.returntype\ +(APIENTRY *flextgl@f.name)(@f.param_type_list_string()); +#define gl@f.name flextgl@f.name + @end + @end +@end +@end + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/MagnumExternal/OpenGL/GLES3/CMakeLists.txt b/src/MagnumExternal/OpenGL/GLES3/CMakeLists.txt index 0cd6050e3..b0e3ed10c 100644 --- a/src/MagnumExternal/OpenGL/GLES3/CMakeLists.txt +++ b/src/MagnumExternal/OpenGL/GLES3/CMakeLists.txt @@ -23,21 +23,35 @@ # DEALINGS IN THE SOFTWARE. # -# flextGLPlatform.cpp is compiled as part of Magnum*Context libraries in Platform -add_library(MagnumFlextGLObjects OBJECT flextGL.cpp) -target_include_directories(MagnumFlextGLObjects PUBLIC $) +# Desktop GLES on Windows still links to opengl32.dll so we have a special +# function loading code that queries everything above OpenGL 1.1 +if(CORRADE_TARGET_WINDOWS AND MAGNUM_TARGET_DESKTOP_GLES) + set(MagnumOpenGL_HEADERS flextGLWindowsDesktop.h) + set(MagnumOpenGL_SRCS flextGLWindowsDesktop.cpp) -if(NOT BUILD_STATIC) - target_compile_definitions(MagnumFlextGLObjects PRIVATE "FlextGL_EXPORTS") -endif() -if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) - set_target_properties(MagnumFlextGLObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) -endif() - -if(CORRADE_TARGET_EMSCRIPTEN) +# Emscripten is special, provide only some extensions for it (and no extension +# loading) +elseif(CORRADE_TARGET_EMSCRIPTEN) set(MagnumOpenGL_HEADERS flextGLEmscripten.h) + +# The common sane case else() set(MagnumOpenGL_HEADERS flextGL.h) + set(MagnumOpenGL_SRCS flextGL.cpp) +endif() + +# Emscripten doesn't have the ability to load function pointers manually +if(NOT CORRADE_TARGET_NACL AND NOT CORRADE_TARGET_EMSCRIPTEN) + # flextGLPlatform*.cpp is compiled as part of Magnum*Context libraries in Platform + add_library(MagnumFlextGLObjects OBJECT ${MagnumOpenGL_SRCS}) + target_include_directories(MagnumFlextGLObjects PUBLIC $) + + if(NOT BUILD_STATIC) + target_compile_definitions(MagnumFlextGLObjects PRIVATE "FlextGL_EXPORTS") + endif() + if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) + set_target_properties(MagnumFlextGLObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() endif() install(FILES ${MagnumOpenGL_HEADERS} DESTINATION ${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR}/OpenGL/GLES3) diff --git a/src/MagnumExternal/OpenGL/GLES3/README.md b/src/MagnumExternal/OpenGL/GLES3/README.md index 680618870..e5e10d786 100644 --- a/src/MagnumExternal/OpenGL/GLES3/README.md +++ b/src/MagnumExternal/OpenGL/GLES3/README.md @@ -1,13 +1,24 @@ OpenGL header and extension loader is generated using flextGL, get it at -[](https://github.com/ginkgo/flextGL). +https://github.com/ginkgo/flextGL. -See [](extensions.txt) for requested version and a list of non-core extensions. -Call `flextGLgen.py` in this directory with the following arguments: +See [extensions.txt](extensions.txt) for requested version and a list of +non-core extensions. Call `flextGLgen.py` in this directory with the following +arguments: .../flextGLgen.py -D . -t . extensions.txt -It will generate `flextGL.h`, `flextGL.cpp`, `flextGLPlatform.cpp` and -`flextGLPlatformIOS.cpp` files. +It will generate `flextGL.h`, `flextGL.cpp`, `flextGLPlatform.cpp`, +`flextGLWindowsDesktop.h`, `flextGLWindowsDesktop.cpp`, +`flextGLPlatformWindowsDesktop.cpp` and `flextGLPlatformIOS.cpp` files. + +Desktop GLES on Windows still links to the ancient `opengl32.dll` which exports +only OpenGL 1.1 symbols, so we have a special set of headers that queries +pointers for everything above OpenGL 1.1 (instead of everything above OpenGL ES +3.0). + +iOS, on the other hand, doesn't have any extension loader mechanism and all +supported entrypoints are exported from the library, so we set the function +pointers to those exported symbols in case the system GL header defines them. Emscripten doesn't have the ability to manually load extension pointers, thus it has only header files: diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGLPlatformWindowsDesktop.cpp b/src/MagnumExternal/OpenGL/GLES3/flextGLPlatformWindowsDesktop.cpp new file mode 100644 index 000000000..a2c38b1b1 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES3/flextGLPlatformWindowsDesktop.cpp @@ -0,0 +1,437 @@ +#include "flextGLWindowsDesktop.h" + +#include +#include + +#include "Magnum/Platform/Implementation/OpenGLFunctionLoader.h" + +void flextGLInit() { + Magnum::Platform::Implementation::OpenGLFunctionLoader loader; + + /* GL_ES_VERSION_2_0 */ + flextglActiveTexture = reinterpret_cast(loader.load("glActiveTexture")); + flextglAttachShader = reinterpret_cast(loader.load("glAttachShader")); + flextglBindAttribLocation = reinterpret_cast(loader.load("glBindAttribLocation")); + flextglBindBuffer = reinterpret_cast(loader.load("glBindBuffer")); + flextglBindFramebuffer = reinterpret_cast(loader.load("glBindFramebuffer")); + flextglBindRenderbuffer = reinterpret_cast(loader.load("glBindRenderbuffer")); + flextglBlendColor = reinterpret_cast(loader.load("glBlendColor")); + flextglBlendEquation = reinterpret_cast(loader.load("glBlendEquation")); + flextglBlendEquationSeparate = reinterpret_cast(loader.load("glBlendEquationSeparate")); + flextglBlendFuncSeparate = reinterpret_cast(loader.load("glBlendFuncSeparate")); + flextglBufferData = reinterpret_cast(loader.load("glBufferData")); + flextglBufferSubData = reinterpret_cast(loader.load("glBufferSubData")); + flextglCheckFramebufferStatus = reinterpret_cast(loader.load("glCheckFramebufferStatus")); + flextglClearDepthf = reinterpret_cast(loader.load("glClearDepthf")); + flextglCompileShader = reinterpret_cast(loader.load("glCompileShader")); + flextglCompressedTexImage2D = reinterpret_cast(loader.load("glCompressedTexImage2D")); + flextglCompressedTexSubImage2D = reinterpret_cast(loader.load("glCompressedTexSubImage2D")); + flextglCreateProgram = reinterpret_cast(loader.load("glCreateProgram")); + flextglCreateShader = reinterpret_cast(loader.load("glCreateShader")); + flextglDeleteBuffers = reinterpret_cast(loader.load("glDeleteBuffers")); + flextglDeleteFramebuffers = reinterpret_cast(loader.load("glDeleteFramebuffers")); + flextglDeleteProgram = reinterpret_cast(loader.load("glDeleteProgram")); + flextglDeleteRenderbuffers = reinterpret_cast(loader.load("glDeleteRenderbuffers")); + flextglDeleteShader = reinterpret_cast(loader.load("glDeleteShader")); + flextglDepthRangef = reinterpret_cast(loader.load("glDepthRangef")); + flextglDetachShader = reinterpret_cast(loader.load("glDetachShader")); + flextglDisableVertexAttribArray = reinterpret_cast(loader.load("glDisableVertexAttribArray")); + flextglEnableVertexAttribArray = reinterpret_cast(loader.load("glEnableVertexAttribArray")); + flextglFramebufferRenderbuffer = reinterpret_cast(loader.load("glFramebufferRenderbuffer")); + flextglFramebufferTexture2D = reinterpret_cast(loader.load("glFramebufferTexture2D")); + flextglGenBuffers = reinterpret_cast(loader.load("glGenBuffers")); + flextglGenFramebuffers = reinterpret_cast(loader.load("glGenFramebuffers")); + flextglGenRenderbuffers = reinterpret_cast(loader.load("glGenRenderbuffers")); + flextglGenerateMipmap = reinterpret_cast(loader.load("glGenerateMipmap")); + flextglGetActiveAttrib = reinterpret_cast(loader.load("glGetActiveAttrib")); + flextglGetActiveUniform = reinterpret_cast(loader.load("glGetActiveUniform")); + flextglGetAttachedShaders = reinterpret_cast(loader.load("glGetAttachedShaders")); + flextglGetAttribLocation = reinterpret_cast(loader.load("glGetAttribLocation")); + flextglGetBufferParameteriv = reinterpret_cast(loader.load("glGetBufferParameteriv")); + flextglGetFramebufferAttachmentParameteriv = reinterpret_cast(loader.load("glGetFramebufferAttachmentParameteriv")); + flextglGetProgramInfoLog = reinterpret_cast(loader.load("glGetProgramInfoLog")); + flextglGetProgramiv = reinterpret_cast(loader.load("glGetProgramiv")); + flextglGetRenderbufferParameteriv = reinterpret_cast(loader.load("glGetRenderbufferParameteriv")); + flextglGetShaderInfoLog = reinterpret_cast(loader.load("glGetShaderInfoLog")); + flextglGetShaderPrecisionFormat = reinterpret_cast(loader.load("glGetShaderPrecisionFormat")); + flextglGetShaderSource = reinterpret_cast(loader.load("glGetShaderSource")); + flextglGetShaderiv = reinterpret_cast(loader.load("glGetShaderiv")); + flextglGetUniformLocation = reinterpret_cast(loader.load("glGetUniformLocation")); + flextglGetUniformfv = reinterpret_cast(loader.load("glGetUniformfv")); + flextglGetUniformiv = reinterpret_cast(loader.load("glGetUniformiv")); + flextglGetVertexAttribPointerv = reinterpret_cast(loader.load("glGetVertexAttribPointerv")); + flextglGetVertexAttribfv = reinterpret_cast(loader.load("glGetVertexAttribfv")); + flextglGetVertexAttribiv = reinterpret_cast(loader.load("glGetVertexAttribiv")); + flextglIsBuffer = reinterpret_cast(loader.load("glIsBuffer")); + flextglIsFramebuffer = reinterpret_cast(loader.load("glIsFramebuffer")); + flextglIsProgram = reinterpret_cast(loader.load("glIsProgram")); + flextglIsRenderbuffer = reinterpret_cast(loader.load("glIsRenderbuffer")); + flextglIsShader = reinterpret_cast(loader.load("glIsShader")); + flextglLinkProgram = reinterpret_cast(loader.load("glLinkProgram")); + flextglReleaseShaderCompiler = reinterpret_cast(loader.load("glReleaseShaderCompiler")); + flextglRenderbufferStorage = reinterpret_cast(loader.load("glRenderbufferStorage")); + flextglSampleCoverage = reinterpret_cast(loader.load("glSampleCoverage")); + flextglShaderBinary = reinterpret_cast(loader.load("glShaderBinary")); + flextglShaderSource = reinterpret_cast(loader.load("glShaderSource")); + flextglStencilFuncSeparate = reinterpret_cast(loader.load("glStencilFuncSeparate")); + flextglStencilMaskSeparate = reinterpret_cast(loader.load("glStencilMaskSeparate")); + flextglStencilOpSeparate = reinterpret_cast(loader.load("glStencilOpSeparate")); + flextglUniform1f = reinterpret_cast(loader.load("glUniform1f")); + flextglUniform1fv = reinterpret_cast(loader.load("glUniform1fv")); + flextglUniform1i = reinterpret_cast(loader.load("glUniform1i")); + flextglUniform1iv = reinterpret_cast(loader.load("glUniform1iv")); + flextglUniform2f = reinterpret_cast(loader.load("glUniform2f")); + flextglUniform2fv = reinterpret_cast(loader.load("glUniform2fv")); + flextglUniform2i = reinterpret_cast(loader.load("glUniform2i")); + flextglUniform2iv = reinterpret_cast(loader.load("glUniform2iv")); + flextglUniform3f = reinterpret_cast(loader.load("glUniform3f")); + flextglUniform3fv = reinterpret_cast(loader.load("glUniform3fv")); + flextglUniform3i = reinterpret_cast(loader.load("glUniform3i")); + flextglUniform3iv = reinterpret_cast(loader.load("glUniform3iv")); + flextglUniform4f = reinterpret_cast(loader.load("glUniform4f")); + flextglUniform4fv = reinterpret_cast(loader.load("glUniform4fv")); + flextglUniform4i = reinterpret_cast(loader.load("glUniform4i")); + flextglUniform4iv = reinterpret_cast(loader.load("glUniform4iv")); + flextglUniformMatrix2fv = reinterpret_cast(loader.load("glUniformMatrix2fv")); + flextglUniformMatrix3fv = reinterpret_cast(loader.load("glUniformMatrix3fv")); + flextglUniformMatrix4fv = reinterpret_cast(loader.load("glUniformMatrix4fv")); + flextglUseProgram = reinterpret_cast(loader.load("glUseProgram")); + flextglValidateProgram = reinterpret_cast(loader.load("glValidateProgram")); + flextglVertexAttrib1f = reinterpret_cast(loader.load("glVertexAttrib1f")); + flextglVertexAttrib1fv = reinterpret_cast(loader.load("glVertexAttrib1fv")); + flextglVertexAttrib2f = reinterpret_cast(loader.load("glVertexAttrib2f")); + flextglVertexAttrib2fv = reinterpret_cast(loader.load("glVertexAttrib2fv")); + flextglVertexAttrib3f = reinterpret_cast(loader.load("glVertexAttrib3f")); + flextglVertexAttrib3fv = reinterpret_cast(loader.load("glVertexAttrib3fv")); + flextglVertexAttrib4f = reinterpret_cast(loader.load("glVertexAttrib4f")); + flextglVertexAttrib4fv = reinterpret_cast(loader.load("glVertexAttrib4fv")); + flextglVertexAttribPointer = reinterpret_cast(loader.load("glVertexAttribPointer")); + + /* GL_ES_VERSION_3_0 */ + flextglBeginQuery = reinterpret_cast(loader.load("glBeginQuery")); + flextglBeginTransformFeedback = reinterpret_cast(loader.load("glBeginTransformFeedback")); + flextglBindBufferBase = reinterpret_cast(loader.load("glBindBufferBase")); + flextglBindBufferRange = reinterpret_cast(loader.load("glBindBufferRange")); + flextglBindSampler = reinterpret_cast(loader.load("glBindSampler")); + flextglBindTransformFeedback = reinterpret_cast(loader.load("glBindTransformFeedback")); + flextglBindVertexArray = reinterpret_cast(loader.load("glBindVertexArray")); + flextglBlitFramebuffer = reinterpret_cast(loader.load("glBlitFramebuffer")); + flextglClearBufferfi = reinterpret_cast(loader.load("glClearBufferfi")); + flextglClearBufferfv = reinterpret_cast(loader.load("glClearBufferfv")); + flextglClearBufferiv = reinterpret_cast(loader.load("glClearBufferiv")); + flextglClearBufferuiv = reinterpret_cast(loader.load("glClearBufferuiv")); + flextglClientWaitSync = reinterpret_cast(loader.load("glClientWaitSync")); + flextglCompressedTexImage3D = reinterpret_cast(loader.load("glCompressedTexImage3D")); + flextglCompressedTexSubImage3D = reinterpret_cast(loader.load("glCompressedTexSubImage3D")); + flextglCopyBufferSubData = reinterpret_cast(loader.load("glCopyBufferSubData")); + flextglCopyTexSubImage3D = reinterpret_cast(loader.load("glCopyTexSubImage3D")); + flextglDeleteQueries = reinterpret_cast(loader.load("glDeleteQueries")); + flextglDeleteSamplers = reinterpret_cast(loader.load("glDeleteSamplers")); + flextglDeleteSync = reinterpret_cast(loader.load("glDeleteSync")); + flextglDeleteTransformFeedbacks = reinterpret_cast(loader.load("glDeleteTransformFeedbacks")); + flextglDeleteVertexArrays = reinterpret_cast(loader.load("glDeleteVertexArrays")); + flextglDrawArraysInstanced = reinterpret_cast(loader.load("glDrawArraysInstanced")); + flextglDrawBuffers = reinterpret_cast(loader.load("glDrawBuffers")); + flextglDrawElementsInstanced = reinterpret_cast(loader.load("glDrawElementsInstanced")); + flextglDrawRangeElements = reinterpret_cast(loader.load("glDrawRangeElements")); + flextglEndQuery = reinterpret_cast(loader.load("glEndQuery")); + flextglEndTransformFeedback = reinterpret_cast(loader.load("glEndTransformFeedback")); + flextglFenceSync = reinterpret_cast(loader.load("glFenceSync")); + flextglFlushMappedBufferRange = reinterpret_cast(loader.load("glFlushMappedBufferRange")); + flextglFramebufferTextureLayer = reinterpret_cast(loader.load("glFramebufferTextureLayer")); + flextglGenQueries = reinterpret_cast(loader.load("glGenQueries")); + flextglGenSamplers = reinterpret_cast(loader.load("glGenSamplers")); + flextglGenTransformFeedbacks = reinterpret_cast(loader.load("glGenTransformFeedbacks")); + flextglGenVertexArrays = reinterpret_cast(loader.load("glGenVertexArrays")); + flextglGetActiveUniformBlockName = reinterpret_cast(loader.load("glGetActiveUniformBlockName")); + flextglGetActiveUniformBlockiv = reinterpret_cast(loader.load("glGetActiveUniformBlockiv")); + flextglGetActiveUniformsiv = reinterpret_cast(loader.load("glGetActiveUniformsiv")); + flextglGetBufferParameteri64v = reinterpret_cast(loader.load("glGetBufferParameteri64v")); + flextglGetBufferPointerv = reinterpret_cast(loader.load("glGetBufferPointerv")); + flextglGetFragDataLocation = reinterpret_cast(loader.load("glGetFragDataLocation")); + flextglGetInteger64i_v = reinterpret_cast(loader.load("glGetInteger64i_v")); + flextglGetInteger64v = reinterpret_cast(loader.load("glGetInteger64v")); + flextglGetIntegeri_v = reinterpret_cast(loader.load("glGetIntegeri_v")); + flextglGetInternalformativ = reinterpret_cast(loader.load("glGetInternalformativ")); + flextglGetProgramBinary = reinterpret_cast(loader.load("glGetProgramBinary")); + flextglGetQueryObjectuiv = reinterpret_cast(loader.load("glGetQueryObjectuiv")); + flextglGetQueryiv = reinterpret_cast(loader.load("glGetQueryiv")); + flextglGetSamplerParameterfv = reinterpret_cast(loader.load("glGetSamplerParameterfv")); + flextglGetSamplerParameteriv = reinterpret_cast(loader.load("glGetSamplerParameteriv")); + flextglGetStringi = reinterpret_cast(loader.load("glGetStringi")); + flextglGetSynciv = reinterpret_cast(loader.load("glGetSynciv")); + flextglGetTransformFeedbackVarying = reinterpret_cast(loader.load("glGetTransformFeedbackVarying")); + flextglGetUniformBlockIndex = reinterpret_cast(loader.load("glGetUniformBlockIndex")); + flextglGetUniformIndices = reinterpret_cast(loader.load("glGetUniformIndices")); + flextglGetUniformuiv = reinterpret_cast(loader.load("glGetUniformuiv")); + flextglGetVertexAttribIiv = reinterpret_cast(loader.load("glGetVertexAttribIiv")); + flextglGetVertexAttribIuiv = reinterpret_cast(loader.load("glGetVertexAttribIuiv")); + flextglInvalidateFramebuffer = reinterpret_cast(loader.load("glInvalidateFramebuffer")); + flextglInvalidateSubFramebuffer = reinterpret_cast(loader.load("glInvalidateSubFramebuffer")); + flextglIsQuery = reinterpret_cast(loader.load("glIsQuery")); + flextglIsSampler = reinterpret_cast(loader.load("glIsSampler")); + flextglIsSync = reinterpret_cast(loader.load("glIsSync")); + flextglIsTransformFeedback = reinterpret_cast(loader.load("glIsTransformFeedback")); + flextglIsVertexArray = reinterpret_cast(loader.load("glIsVertexArray")); + flextglMapBufferRange = reinterpret_cast(loader.load("glMapBufferRange")); + flextglPauseTransformFeedback = reinterpret_cast(loader.load("glPauseTransformFeedback")); + flextglProgramBinary = reinterpret_cast(loader.load("glProgramBinary")); + flextglProgramParameteri = reinterpret_cast(loader.load("glProgramParameteri")); + flextglRenderbufferStorageMultisample = reinterpret_cast(loader.load("glRenderbufferStorageMultisample")); + flextglResumeTransformFeedback = reinterpret_cast(loader.load("glResumeTransformFeedback")); + flextglSamplerParameterf = reinterpret_cast(loader.load("glSamplerParameterf")); + flextglSamplerParameterfv = reinterpret_cast(loader.load("glSamplerParameterfv")); + flextglSamplerParameteri = reinterpret_cast(loader.load("glSamplerParameteri")); + flextglSamplerParameteriv = reinterpret_cast(loader.load("glSamplerParameteriv")); + flextglTexImage3D = reinterpret_cast(loader.load("glTexImage3D")); + flextglTexStorage2D = reinterpret_cast(loader.load("glTexStorage2D")); + flextglTexStorage3D = reinterpret_cast(loader.load("glTexStorage3D")); + flextglTexSubImage3D = reinterpret_cast(loader.load("glTexSubImage3D")); + flextglTransformFeedbackVaryings = reinterpret_cast(loader.load("glTransformFeedbackVaryings")); + flextglUniform1ui = reinterpret_cast(loader.load("glUniform1ui")); + flextglUniform1uiv = reinterpret_cast(loader.load("glUniform1uiv")); + flextglUniform2ui = reinterpret_cast(loader.load("glUniform2ui")); + flextglUniform2uiv = reinterpret_cast(loader.load("glUniform2uiv")); + flextglUniform3ui = reinterpret_cast(loader.load("glUniform3ui")); + flextglUniform3uiv = reinterpret_cast(loader.load("glUniform3uiv")); + flextglUniform4ui = reinterpret_cast(loader.load("glUniform4ui")); + flextglUniform4uiv = reinterpret_cast(loader.load("glUniform4uiv")); + flextglUniformBlockBinding = reinterpret_cast(loader.load("glUniformBlockBinding")); + flextglUniformMatrix2x3fv = reinterpret_cast(loader.load("glUniformMatrix2x3fv")); + flextglUniformMatrix2x4fv = reinterpret_cast(loader.load("glUniformMatrix2x4fv")); + flextglUniformMatrix3x2fv = reinterpret_cast(loader.load("glUniformMatrix3x2fv")); + flextglUniformMatrix3x4fv = reinterpret_cast(loader.load("glUniformMatrix3x4fv")); + flextglUniformMatrix4x2fv = reinterpret_cast(loader.load("glUniformMatrix4x2fv")); + flextglUniformMatrix4x3fv = reinterpret_cast(loader.load("glUniformMatrix4x3fv")); + flextglUnmapBuffer = reinterpret_cast(loader.load("glUnmapBuffer")); + flextglVertexAttribDivisor = reinterpret_cast(loader.load("glVertexAttribDivisor")); + flextglVertexAttribI4i = reinterpret_cast(loader.load("glVertexAttribI4i")); + flextglVertexAttribI4iv = reinterpret_cast(loader.load("glVertexAttribI4iv")); + flextglVertexAttribI4ui = reinterpret_cast(loader.load("glVertexAttribI4ui")); + flextglVertexAttribI4uiv = reinterpret_cast(loader.load("glVertexAttribI4uiv")); + flextglVertexAttribIPointer = reinterpret_cast(loader.load("glVertexAttribIPointer")); + flextglWaitSync = reinterpret_cast(loader.load("glWaitSync")); + + /* GL_ES_VERSION_3_1 */ + flextglActiveShaderProgram = reinterpret_cast(loader.load("glActiveShaderProgram")); + flextglBindImageTexture = reinterpret_cast(loader.load("glBindImageTexture")); + flextglBindProgramPipeline = reinterpret_cast(loader.load("glBindProgramPipeline")); + flextglBindVertexBuffer = reinterpret_cast(loader.load("glBindVertexBuffer")); + flextglCreateShaderProgramv = reinterpret_cast(loader.load("glCreateShaderProgramv")); + flextglDeleteProgramPipelines = reinterpret_cast(loader.load("glDeleteProgramPipelines")); + flextglDispatchCompute = reinterpret_cast(loader.load("glDispatchCompute")); + flextglDispatchComputeIndirect = reinterpret_cast(loader.load("glDispatchComputeIndirect")); + flextglDrawArraysIndirect = reinterpret_cast(loader.load("glDrawArraysIndirect")); + flextglDrawElementsIndirect = reinterpret_cast(loader.load("glDrawElementsIndirect")); + flextglFramebufferParameteri = reinterpret_cast(loader.load("glFramebufferParameteri")); + flextglGenProgramPipelines = reinterpret_cast(loader.load("glGenProgramPipelines")); + flextglGetBooleani_v = reinterpret_cast(loader.load("glGetBooleani_v")); + flextglGetFramebufferParameteriv = reinterpret_cast(loader.load("glGetFramebufferParameteriv")); + flextglGetMultisamplefv = reinterpret_cast(loader.load("glGetMultisamplefv")); + flextglGetProgramInterfaceiv = reinterpret_cast(loader.load("glGetProgramInterfaceiv")); + flextglGetProgramPipelineInfoLog = reinterpret_cast(loader.load("glGetProgramPipelineInfoLog")); + flextglGetProgramPipelineiv = reinterpret_cast(loader.load("glGetProgramPipelineiv")); + flextglGetProgramResourceIndex = reinterpret_cast(loader.load("glGetProgramResourceIndex")); + flextglGetProgramResourceLocation = reinterpret_cast(loader.load("glGetProgramResourceLocation")); + flextglGetProgramResourceName = reinterpret_cast(loader.load("glGetProgramResourceName")); + flextglGetProgramResourceiv = reinterpret_cast(loader.load("glGetProgramResourceiv")); + flextglIsProgramPipeline = reinterpret_cast(loader.load("glIsProgramPipeline")); + flextglMemoryBarrier = reinterpret_cast(loader.load("glMemoryBarrier")); + flextglMemoryBarrierByRegion = reinterpret_cast(loader.load("glMemoryBarrierByRegion")); + flextglProgramUniform1f = reinterpret_cast(loader.load("glProgramUniform1f")); + flextglProgramUniform1fv = reinterpret_cast(loader.load("glProgramUniform1fv")); + flextglProgramUniform1i = reinterpret_cast(loader.load("glProgramUniform1i")); + flextglProgramUniform1iv = reinterpret_cast(loader.load("glProgramUniform1iv")); + flextglProgramUniform1ui = reinterpret_cast(loader.load("glProgramUniform1ui")); + flextglProgramUniform1uiv = reinterpret_cast(loader.load("glProgramUniform1uiv")); + flextglProgramUniform2f = reinterpret_cast(loader.load("glProgramUniform2f")); + flextglProgramUniform2fv = reinterpret_cast(loader.load("glProgramUniform2fv")); + flextglProgramUniform2i = reinterpret_cast(loader.load("glProgramUniform2i")); + flextglProgramUniform2iv = reinterpret_cast(loader.load("glProgramUniform2iv")); + flextglProgramUniform2ui = reinterpret_cast(loader.load("glProgramUniform2ui")); + flextglProgramUniform2uiv = reinterpret_cast(loader.load("glProgramUniform2uiv")); + flextglProgramUniform3f = reinterpret_cast(loader.load("glProgramUniform3f")); + flextglProgramUniform3fv = reinterpret_cast(loader.load("glProgramUniform3fv")); + flextglProgramUniform3i = reinterpret_cast(loader.load("glProgramUniform3i")); + flextglProgramUniform3iv = reinterpret_cast(loader.load("glProgramUniform3iv")); + flextglProgramUniform3ui = reinterpret_cast(loader.load("glProgramUniform3ui")); + flextglProgramUniform3uiv = reinterpret_cast(loader.load("glProgramUniform3uiv")); + flextglProgramUniform4f = reinterpret_cast(loader.load("glProgramUniform4f")); + flextglProgramUniform4fv = reinterpret_cast(loader.load("glProgramUniform4fv")); + flextglProgramUniform4i = reinterpret_cast(loader.load("glProgramUniform4i")); + flextglProgramUniform4iv = reinterpret_cast(loader.load("glProgramUniform4iv")); + flextglProgramUniform4ui = reinterpret_cast(loader.load("glProgramUniform4ui")); + flextglProgramUniform4uiv = reinterpret_cast(loader.load("glProgramUniform4uiv")); + flextglProgramUniformMatrix2fv = reinterpret_cast(loader.load("glProgramUniformMatrix2fv")); + flextglProgramUniformMatrix2x3fv = reinterpret_cast(loader.load("glProgramUniformMatrix2x3fv")); + flextglProgramUniformMatrix2x4fv = reinterpret_cast(loader.load("glProgramUniformMatrix2x4fv")); + flextglProgramUniformMatrix3fv = reinterpret_cast(loader.load("glProgramUniformMatrix3fv")); + flextglProgramUniformMatrix3x2fv = reinterpret_cast(loader.load("glProgramUniformMatrix3x2fv")); + flextglProgramUniformMatrix3x4fv = reinterpret_cast(loader.load("glProgramUniformMatrix3x4fv")); + flextglProgramUniformMatrix4fv = reinterpret_cast(loader.load("glProgramUniformMatrix4fv")); + flextglProgramUniformMatrix4x2fv = reinterpret_cast(loader.load("glProgramUniformMatrix4x2fv")); + flextglProgramUniformMatrix4x3fv = reinterpret_cast(loader.load("glProgramUniformMatrix4x3fv")); + flextglSampleMaski = reinterpret_cast(loader.load("glSampleMaski")); + flextglTexStorage2DMultisample = reinterpret_cast(loader.load("glTexStorage2DMultisample")); + flextglUseProgramStages = reinterpret_cast(loader.load("glUseProgramStages")); + flextglValidateProgramPipeline = reinterpret_cast(loader.load("glValidateProgramPipeline")); + flextglVertexAttribBinding = reinterpret_cast(loader.load("glVertexAttribBinding")); + flextglVertexAttribFormat = reinterpret_cast(loader.load("glVertexAttribFormat")); + flextglVertexAttribIFormat = reinterpret_cast(loader.load("glVertexAttribIFormat")); + flextglVertexBindingDivisor = reinterpret_cast(loader.load("glVertexBindingDivisor")); + + /* GL_EXT_copy_image */ + flextglCopyImageSubDataEXT = reinterpret_cast(loader.load("glCopyImageSubDataEXT")); + + /* GL_EXT_debug_label */ + flextglGetObjectLabelEXT = reinterpret_cast(loader.load("glGetObjectLabelEXT")); + flextglLabelObjectEXT = reinterpret_cast(loader.load("glLabelObjectEXT")); + + /* GL_EXT_debug_marker */ + flextglInsertEventMarkerEXT = reinterpret_cast(loader.load("glInsertEventMarkerEXT")); + flextglPopGroupMarkerEXT = reinterpret_cast(loader.load("glPopGroupMarkerEXT")); + flextglPushGroupMarkerEXT = reinterpret_cast(loader.load("glPushGroupMarkerEXT")); + + /* GL_EXT_disjoint_timer_query */ + flextglBeginQueryEXT = reinterpret_cast(loader.load("glBeginQueryEXT")); + flextglDeleteQueriesEXT = reinterpret_cast(loader.load("glDeleteQueriesEXT")); + flextglEndQueryEXT = reinterpret_cast(loader.load("glEndQueryEXT")); + flextglGenQueriesEXT = reinterpret_cast(loader.load("glGenQueriesEXT")); + flextglGetQueryObjecti64vEXT = reinterpret_cast(loader.load("glGetQueryObjecti64vEXT")); + flextglGetQueryObjectivEXT = reinterpret_cast(loader.load("glGetQueryObjectivEXT")); + flextglGetQueryObjectui64vEXT = reinterpret_cast(loader.load("glGetQueryObjectui64vEXT")); + flextglGetQueryObjectuivEXT = reinterpret_cast(loader.load("glGetQueryObjectuivEXT")); + flextglGetQueryivEXT = reinterpret_cast(loader.load("glGetQueryivEXT")); + flextglIsQueryEXT = reinterpret_cast(loader.load("glIsQueryEXT")); + flextglQueryCounterEXT = reinterpret_cast(loader.load("glQueryCounterEXT")); + + /* GL_EXT_draw_buffers_indexed */ + flextglBlendEquationSeparateiEXT = reinterpret_cast(loader.load("glBlendEquationSeparateiEXT")); + flextglBlendEquationiEXT = reinterpret_cast(loader.load("glBlendEquationiEXT")); + flextglBlendFuncSeparateiEXT = reinterpret_cast(loader.load("glBlendFuncSeparateiEXT")); + flextglBlendFunciEXT = reinterpret_cast(loader.load("glBlendFunciEXT")); + flextglColorMaskiEXT = reinterpret_cast(loader.load("glColorMaskiEXT")); + flextglDisableiEXT = reinterpret_cast(loader.load("glDisableiEXT")); + flextglEnableiEXT = reinterpret_cast(loader.load("glEnableiEXT")); + flextglIsEnablediEXT = reinterpret_cast(loader.load("glIsEnablediEXT")); + + /* GL_EXT_geometry_shader */ + flextglFramebufferTextureEXT = reinterpret_cast(loader.load("glFramebufferTextureEXT")); + + /* GL_EXT_multi_draw_arrays */ + flextglMultiDrawArraysEXT = reinterpret_cast(loader.load("glMultiDrawArraysEXT")); + flextglMultiDrawElementsEXT = reinterpret_cast(loader.load("glMultiDrawElementsEXT")); + + /* GL_EXT_multisampled_render_to_texture */ + flextglFramebufferTexture2DMultisampleEXT = reinterpret_cast(loader.load("glFramebufferTexture2DMultisampleEXT")); + flextglRenderbufferStorageMultisampleEXT = reinterpret_cast(loader.load("glRenderbufferStorageMultisampleEXT")); + + /* GL_EXT_primitive_bounding_box */ + flextglPrimitiveBoundingBoxEXT = reinterpret_cast(loader.load("glPrimitiveBoundingBoxEXT")); + + /* GL_EXT_robustness */ + flextglGetGraphicsResetStatusEXT = reinterpret_cast(loader.load("glGetGraphicsResetStatusEXT")); + flextglGetnUniformfvEXT = reinterpret_cast(loader.load("glGetnUniformfvEXT")); + flextglGetnUniformivEXT = reinterpret_cast(loader.load("glGetnUniformivEXT")); + flextglReadnPixelsEXT = reinterpret_cast(loader.load("glReadnPixelsEXT")); + + /* GL_EXT_separate_shader_objects */ + flextglActiveShaderProgramEXT = reinterpret_cast(loader.load("glActiveShaderProgramEXT")); + flextglBindProgramPipelineEXT = reinterpret_cast(loader.load("glBindProgramPipelineEXT")); + flextglCreateShaderProgramvEXT = reinterpret_cast(loader.load("glCreateShaderProgramvEXT")); + flextglDeleteProgramPipelinesEXT = reinterpret_cast(loader.load("glDeleteProgramPipelinesEXT")); + flextglGenProgramPipelinesEXT = reinterpret_cast(loader.load("glGenProgramPipelinesEXT")); + flextglGetProgramPipelineInfoLogEXT = reinterpret_cast(loader.load("glGetProgramPipelineInfoLogEXT")); + flextglGetProgramPipelineivEXT = reinterpret_cast(loader.load("glGetProgramPipelineivEXT")); + flextglIsProgramPipelineEXT = reinterpret_cast(loader.load("glIsProgramPipelineEXT")); + flextglProgramParameteriEXT = reinterpret_cast(loader.load("glProgramParameteriEXT")); + flextglProgramUniform1fEXT = reinterpret_cast(loader.load("glProgramUniform1fEXT")); + flextglProgramUniform1fvEXT = reinterpret_cast(loader.load("glProgramUniform1fvEXT")); + flextglProgramUniform1iEXT = reinterpret_cast(loader.load("glProgramUniform1iEXT")); + flextglProgramUniform1ivEXT = reinterpret_cast(loader.load("glProgramUniform1ivEXT")); + flextglProgramUniform1uiEXT = reinterpret_cast(loader.load("glProgramUniform1uiEXT")); + flextglProgramUniform1uivEXT = reinterpret_cast(loader.load("glProgramUniform1uivEXT")); + flextglProgramUniform2fEXT = reinterpret_cast(loader.load("glProgramUniform2fEXT")); + flextglProgramUniform2fvEXT = reinterpret_cast(loader.load("glProgramUniform2fvEXT")); + flextglProgramUniform2iEXT = reinterpret_cast(loader.load("glProgramUniform2iEXT")); + flextglProgramUniform2ivEXT = reinterpret_cast(loader.load("glProgramUniform2ivEXT")); + flextglProgramUniform2uiEXT = reinterpret_cast(loader.load("glProgramUniform2uiEXT")); + flextglProgramUniform2uivEXT = reinterpret_cast(loader.load("glProgramUniform2uivEXT")); + flextglProgramUniform3fEXT = reinterpret_cast(loader.load("glProgramUniform3fEXT")); + flextglProgramUniform3fvEXT = reinterpret_cast(loader.load("glProgramUniform3fvEXT")); + flextglProgramUniform3iEXT = reinterpret_cast(loader.load("glProgramUniform3iEXT")); + flextglProgramUniform3ivEXT = reinterpret_cast(loader.load("glProgramUniform3ivEXT")); + flextglProgramUniform3uiEXT = reinterpret_cast(loader.load("glProgramUniform3uiEXT")); + flextglProgramUniform3uivEXT = reinterpret_cast(loader.load("glProgramUniform3uivEXT")); + flextglProgramUniform4fEXT = reinterpret_cast(loader.load("glProgramUniform4fEXT")); + flextglProgramUniform4fvEXT = reinterpret_cast(loader.load("glProgramUniform4fvEXT")); + flextglProgramUniform4iEXT = reinterpret_cast(loader.load("glProgramUniform4iEXT")); + flextglProgramUniform4ivEXT = reinterpret_cast(loader.load("glProgramUniform4ivEXT")); + flextglProgramUniform4uiEXT = reinterpret_cast(loader.load("glProgramUniform4uiEXT")); + flextglProgramUniform4uivEXT = reinterpret_cast(loader.load("glProgramUniform4uivEXT")); + flextglProgramUniformMatrix2fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix2fvEXT")); + flextglProgramUniformMatrix2x3fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix2x3fvEXT")); + flextglProgramUniformMatrix2x4fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix2x4fvEXT")); + flextglProgramUniformMatrix3fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix3fvEXT")); + flextglProgramUniformMatrix3x2fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix3x2fvEXT")); + flextglProgramUniformMatrix3x4fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix3x4fvEXT")); + flextglProgramUniformMatrix4fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix4fvEXT")); + flextglProgramUniformMatrix4x2fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix4x2fvEXT")); + flextglProgramUniformMatrix4x3fvEXT = reinterpret_cast(loader.load("glProgramUniformMatrix4x3fvEXT")); + flextglUseProgramStagesEXT = reinterpret_cast(loader.load("glUseProgramStagesEXT")); + flextglValidateProgramPipelineEXT = reinterpret_cast(loader.load("glValidateProgramPipelineEXT")); + + /* GL_EXT_tessellation_shader */ + flextglPatchParameteriEXT = reinterpret_cast(loader.load("glPatchParameteriEXT")); + + /* GL_EXT_texture_border_clamp */ + flextglGetSamplerParameterIivEXT = reinterpret_cast(loader.load("glGetSamplerParameterIivEXT")); + flextglGetSamplerParameterIuivEXT = reinterpret_cast(loader.load("glGetSamplerParameterIuivEXT")); + flextglGetTexParameterIivEXT = reinterpret_cast(loader.load("glGetTexParameterIivEXT")); + flextglGetTexParameterIuivEXT = reinterpret_cast(loader.load("glGetTexParameterIuivEXT")); + flextglSamplerParameterIivEXT = reinterpret_cast(loader.load("glSamplerParameterIivEXT")); + flextglSamplerParameterIuivEXT = reinterpret_cast(loader.load("glSamplerParameterIuivEXT")); + flextglTexParameterIivEXT = reinterpret_cast(loader.load("glTexParameterIivEXT")); + flextglTexParameterIuivEXT = reinterpret_cast(loader.load("glTexParameterIuivEXT")); + + /* GL_EXT_texture_buffer */ + flextglTexBufferEXT = reinterpret_cast(loader.load("glTexBufferEXT")); + flextglTexBufferRangeEXT = reinterpret_cast(loader.load("glTexBufferRangeEXT")); + + /* GL_KHR_blend_equation_advanced */ + flextglBlendBarrierKHR = reinterpret_cast(loader.load("glBlendBarrierKHR")); + + /* GL_KHR_debug */ + flextglDebugMessageCallbackKHR = reinterpret_cast(loader.load("glDebugMessageCallbackKHR")); + flextglDebugMessageControlKHR = reinterpret_cast(loader.load("glDebugMessageControlKHR")); + flextglDebugMessageInsertKHR = reinterpret_cast(loader.load("glDebugMessageInsertKHR")); + flextglGetDebugMessageLogKHR = reinterpret_cast(loader.load("glGetDebugMessageLogKHR")); + flextglGetObjectLabelKHR = reinterpret_cast(loader.load("glGetObjectLabelKHR")); + flextglGetObjectPtrLabelKHR = reinterpret_cast(loader.load("glGetObjectPtrLabelKHR")); + flextglGetPointervKHR = reinterpret_cast(loader.load("glGetPointervKHR")); + flextglObjectLabelKHR = reinterpret_cast(loader.load("glObjectLabelKHR")); + flextglObjectPtrLabelKHR = reinterpret_cast(loader.load("glObjectPtrLabelKHR")); + flextglPopDebugGroupKHR = reinterpret_cast(loader.load("glPopDebugGroupKHR")); + flextglPushDebugGroupKHR = reinterpret_cast(loader.load("glPushDebugGroupKHR")); + + /* GL_KHR_robustness */ + flextglGetGraphicsResetStatusKHR = reinterpret_cast(loader.load("glGetGraphicsResetStatusKHR")); + flextglGetnUniformfvKHR = reinterpret_cast(loader.load("glGetnUniformfvKHR")); + flextglGetnUniformivKHR = reinterpret_cast(loader.load("glGetnUniformivKHR")); + flextglGetnUniformuivKHR = reinterpret_cast(loader.load("glGetnUniformuivKHR")); + flextglReadnPixelsKHR = reinterpret_cast(loader.load("glReadnPixelsKHR")); + + /* GL_NV_polygon_mode */ + flextglPolygonModeNV = reinterpret_cast(loader.load("glPolygonModeNV")); + + /* GL_OES_mapbuffer */ + flextglGetBufferPointervOES = reinterpret_cast(loader.load("glGetBufferPointervOES")); + flextglMapBufferOES = reinterpret_cast(loader.load("glMapBufferOES")); + flextglUnmapBufferOES = reinterpret_cast(loader.load("glUnmapBufferOES")); + + /* GL_OES_sample_shading */ + flextglMinSampleShadingOES = reinterpret_cast(loader.load("glMinSampleShadingOES")); + + /* GL_OES_texture_storage_multisample_2d_array */ + flextglTexStorage3DMultisampleOES = reinterpret_cast(loader.load("glTexStorage3DMultisampleOES")); +} diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGLPlatformWindowsDesktop.cpp.template b/src/MagnumExternal/OpenGL/GLES3/flextGLPlatformWindowsDesktop.cpp.template new file mode 100644 index 000000000..8af659565 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES3/flextGLPlatformWindowsDesktop.cpp.template @@ -0,0 +1,23 @@ +@require(passthru, functions, enums, options, version, extensions) +#include "flextGLWindowsDesktop.h" + +#include +#include + +#include "Magnum/Platform/Implementation/OpenGLFunctionLoader.h" + +void flextGLInit() { + Magnum::Platform::Implementation::OpenGLFunctionLoader loader; + @for category,funcs in functions: + @if funcs: + + /* GL_@category */ + @for f in funcs: + @if f.name not in ['BlendFunc', 'Clear', 'ClearColor', 'ClearDepth', 'ClearStencil', 'ColorMask', 'CullFace', 'DepthFunc', 'DepthMask', 'DepthRange', 'Disable', 'DrawBuffer', 'Enable', 'Finish', 'Flush', 'FrontFace', 'GetBooleanv', 'GetDoublev', 'GetError', 'GetFloatv', 'GetIntegerv', 'GetString', 'GetTexImage', 'GetTexLevelParameterfv', 'GetTexLevelParameteriv', 'GetTexParameterfv', 'GetTexParameteriv', 'Hint', 'IsEnabled', 'LineWidth', 'LogicOp', 'PixelStoref', 'PixelStorei', 'PointSize', 'PolygonMode', 'ReadBuffer', 'ReadPixels', 'Scissor', 'StencilFunc', 'StencilMask', 'StencilOp', 'TexImage1D', 'TexImage2D', 'TexParameterf', 'TexParameterfv', 'TexParameteri', 'TexParameteriv', 'Viewport', 'BindTexture', 'CopyTexImage1D', 'CopyTexImage2D', 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'DeleteTextures', 'DrawArrays', 'DrawElements', 'GenTextures', 'IsTexture', 'PolygonOffset', 'TexSubImage1D', 'TexSubImage2D']: + flextgl@f.name = reinterpret_cast<@f.returntype\ +(APIENTRY*)(@f.param_type_list_string())>(loader.load("gl@f.name")); + @end + @end + @end + @end +} diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.cpp b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.cpp new file mode 100644 index 000000000..cb3b19a22 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.cpp @@ -0,0 +1,436 @@ +#include "flextGLWindowsDesktop.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* GL_ES_VERSION_2_0 */ +FLEXTGL_EXPORT void(APIENTRY *flextglActiveTexture)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglAttachShader)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindAttribLocation)(GLuint, GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindBuffer)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindFramebuffer)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindRenderbuffer)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendColor)(GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquation)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparate)(GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparate)(GLenum, GLenum, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBufferData)(GLenum, GLsizeiptr, const void *, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBufferSubData)(GLenum, GLintptr, GLsizeiptr, const void *) = nullptr; +FLEXTGL_EXPORT GLenum(APIENTRY *flextglCheckFramebufferStatus)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglClearDepthf)(GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompileShader)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage2D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateProgram)(void) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShader)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteBuffers)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteFramebuffers)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteRenderbuffers)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteShader)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDepthRangef)(GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDetachShader)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDisableVertexAttribArray)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEnableVertexAttribArray)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenBuffers)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenFramebuffers)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenRenderbuffers)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenerateMipmap)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveAttrib)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniform)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetAttachedShaders)(GLuint, GLsizei, GLsizei *, GLuint *) = nullptr; +FLEXTGL_EXPORT GLint(APIENTRY *flextglGetAttribLocation)(GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferParameteriv)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetFramebufferAttachmentParameteriv)(GLenum, GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetRenderbufferParameteriv)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderPrecisionFormat)(GLenum, GLenum, GLint *, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderSource)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLint(APIENTRY *flextglGetUniformLocation)(GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformfv)(GLuint, GLint, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformiv)(GLuint, GLint, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribPointerv)(GLuint, GLenum, void **) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribfv)(GLuint, GLenum, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsBuffer)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsFramebuffer)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsRenderbuffer)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsShader)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglLinkProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglReleaseShaderCompiler)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSampleCoverage)(GLfloat, GLboolean) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglShaderBinary)(GLsizei, const GLuint *, GLenum, const void *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglShaderSource)(GLuint, GLsizei, const GLchar *const*, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglStencilMaskSeparate)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1f)(GLint, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1i)(GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2f)(GLint, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2i)(GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3f)(GLint, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3i)(GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4fv)(GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4i)(GLint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4iv)(GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUseProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgram)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1f)(GLuint, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2f)(GLuint, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3f)(GLuint, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4f)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4fv)(GLuint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *) = nullptr; + +/* GL_ES_VERSION_3_0 */ +FLEXTGL_EXPORT void(APIENTRY *flextglBeginQuery)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBeginTransformFeedback)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindBufferBase)(GLenum, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindBufferRange)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindSampler)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindTransformFeedback)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindVertexArray)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlitFramebuffer)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferfi)(GLenum, GLint, GLfloat, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferfv)(GLenum, GLint, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferiv)(GLenum, GLint, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferuiv)(GLenum, GLint, const GLuint *) = nullptr; +FLEXTGL_EXPORT GLenum(APIENTRY *flextglClientWaitSync)(GLsync, GLbitfield, GLuint64) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage3D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglCopyTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteQueries)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteSamplers)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteSync)(GLsync) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteTransformFeedbacks)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteVertexArrays)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstanced)(GLenum, GLint, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawBuffers)(GLsizei, const GLenum *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstanced)(GLenum, GLsizei, GLenum, const void *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawRangeElements)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEndQuery)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEndTransformFeedback)(void) = nullptr; +FLEXTGL_EXPORT GLsync(APIENTRY *flextglFenceSync)(GLenum, GLbitfield) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFlushMappedBufferRange)(GLenum, GLintptr, GLsizeiptr) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTextureLayer)(GLenum, GLenum, GLuint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenQueries)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenSamplers)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenTransformFeedbacks)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenVertexArrays)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniformBlockName)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniformBlockiv)(GLuint, GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniformsiv)(GLuint, GLsizei, const GLuint *, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferParameteri64v)(GLenum, GLenum, GLint64 *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferPointerv)(GLenum, GLenum, void **) = nullptr; +FLEXTGL_EXPORT GLint(APIENTRY *flextglGetFragDataLocation)(GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetInteger64i_v)(GLenum, GLuint, GLint64 *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetInteger64v)(GLenum, GLint64 *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetIntegeri_v)(GLenum, GLuint, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetInternalformativ)(GLenum, GLenum, GLenum, GLsizei, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramBinary)(GLuint, GLsizei, GLsizei *, GLenum *, void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectuiv)(GLuint, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryiv)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterfv)(GLuint, GLenum, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameteriv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT const GLubyte *(APIENTRY *flextglGetStringi)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetSynciv)(GLsync, GLenum, GLsizei, GLsizei *, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetTransformFeedbackVarying)(GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetUniformBlockIndex)(GLuint, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformIndices)(GLuint, GLsizei, const GLchar *const*, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformuiv)(GLuint, GLint, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribIiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribIuiv)(GLuint, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglInvalidateFramebuffer)(GLenum, GLsizei, const GLenum *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglInvalidateSubFramebuffer)(GLenum, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsQuery)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsSampler)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsSync)(GLsync) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsTransformFeedback)(GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsVertexArray)(GLuint) = nullptr; +FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferRange)(GLenum, GLintptr, GLsizeiptr, GLbitfield) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPauseTransformFeedback)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramBinary)(GLuint, GLenum, const void *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramParameteri)(GLuint, GLenum, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisample)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglResumeTransformFeedback)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterf)(GLuint, GLenum, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterfv)(GLuint, GLenum, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameteri)(GLuint, GLenum, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameteriv)(GLuint, GLenum, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexImage3D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2D)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3D)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTransformFeedbackVaryings)(GLuint, GLsizei, const GLchar *const*, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1ui)(GLint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform1uiv)(GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2ui)(GLint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform2uiv)(GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3ui)(GLint, GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform3uiv)(GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4ui)(GLint, GLuint, GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniform4uiv)(GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformBlockBinding)(GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2x3fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2x4fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3x2fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3x4fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4x2fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4x3fv)(GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglUnmapBuffer)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisor)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4i)(GLuint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4iv)(GLuint, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4ui)(GLuint, GLuint, GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4uiv)(GLuint, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribIPointer)(GLuint, GLint, GLenum, GLsizei, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglWaitSync)(GLsync, GLbitfield, GLuint64) = nullptr; + +/* GL_ES_VERSION_3_1 */ +FLEXTGL_EXPORT void(APIENTRY *flextglActiveShaderProgram)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindImageTexture)(GLuint, GLuint, GLint, GLboolean, GLint, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindProgramPipeline)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindVertexBuffer)(GLuint, GLuint, GLintptr, GLsizei) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShaderProgramv)(GLenum, GLsizei, const GLchar *const*) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgramPipelines)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDispatchCompute)(GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDispatchComputeIndirect)(GLintptr) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysIndirect)(GLenum, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsIndirect)(GLenum, GLenum, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferParameteri)(GLenum, GLenum, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenProgramPipelines)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetBooleani_v)(GLenum, GLuint, GLboolean *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetFramebufferParameteriv)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetMultisamplefv)(GLenum, GLuint, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramInterfaceiv)(GLuint, GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineiv)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetProgramResourceIndex)(GLuint, GLenum, const GLchar *) = nullptr; +FLEXTGL_EXPORT GLint(APIENTRY *flextglGetProgramResourceLocation)(GLuint, GLenum, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramResourceName)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramResourceiv)(GLuint, GLenum, GLuint, GLsizei, const GLenum *, GLsizei, GLsizei *, GLint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgramPipeline)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglMemoryBarrier)(GLbitfield) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglMemoryBarrierByRegion)(GLbitfield) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1f)(GLuint, GLint, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fv)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1i)(GLuint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iv)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ui)(GLuint, GLint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uiv)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2f)(GLuint, GLint, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fv)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2i)(GLuint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iv)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ui)(GLuint, GLint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uiv)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3f)(GLuint, GLint, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fv)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3i)(GLuint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iv)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ui)(GLuint, GLint, GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uiv)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4f)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fv)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4i)(GLuint, GLint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iv)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ui)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uiv)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x3fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x4fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x2fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x4fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x2fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x3fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSampleMaski)(GLuint, GLbitfield) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2DMultisample)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStages)(GLuint, GLbitfield, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipeline)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribBinding)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribFormat)(GLuint, GLint, GLenum, GLboolean, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribIFormat)(GLuint, GLint, GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglVertexBindingDivisor)(GLuint, GLuint) = nullptr; + +/* GL_EXT_copy_image */ +FLEXTGL_EXPORT void(APIENTRY *flextglCopyImageSubDataEXT)(GLuint, GLenum, GLint, GLint, GLint, GLint, GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei) = nullptr; + +/* GL_EXT_debug_label */ +FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelEXT)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglLabelObjectEXT)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; + +/* GL_EXT_debug_marker */ +FLEXTGL_EXPORT void(APIENTRY *flextglInsertEventMarkerEXT)(GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPopGroupMarkerEXT)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPushGroupMarkerEXT)(GLsizei, const GLchar *) = nullptr; + +/* GL_EXT_disjoint_timer_query */ +FLEXTGL_EXPORT void(APIENTRY *flextglBeginQueryEXT)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteQueriesEXT)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEndQueryEXT)(GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenQueriesEXT)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjecti64vEXT)(GLuint, GLenum, GLint64 *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectivEXT)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectui64vEXT)(GLuint, GLenum, GLuint64 *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectuivEXT)(GLuint, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryivEXT)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsQueryEXT)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglQueryCounterEXT)(GLuint, GLenum) = nullptr; + +/* GL_EXT_draw_buffers_indexed */ +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparateiEXT)(GLuint, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationiEXT)(GLuint, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparateiEXT)(GLuint, GLenum, GLenum, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBlendFunciEXT)(GLuint, GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglColorMaskiEXT)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDisableiEXT)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglEnableiEXT)(GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsEnablediEXT)(GLenum, GLuint) = nullptr; + +/* GL_EXT_geometry_shader */ +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTextureEXT)(GLenum, GLenum, GLuint, GLint) = nullptr; + +/* GL_EXT_multi_draw_arrays */ +FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawArraysEXT)(GLenum, const GLint *, const GLsizei *, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawElementsEXT)(GLenum, const GLsizei *, GLenum, const void *const*, GLsizei) = nullptr; + +/* GL_EXT_multisampled_render_to_texture */ +FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2DMultisampleEXT)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = nullptr; + +/* GL_EXT_primitive_bounding_box */ +FLEXTGL_EXPORT void(APIENTRY *flextglPrimitiveBoundingBoxEXT)(GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; + +/* GL_EXT_robustness */ +FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusEXT)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvEXT)(GLuint, GLint, GLsizei, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivEXT)(GLuint, GLint, GLsizei, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsEXT)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *) = nullptr; + +/* GL_EXT_separate_shader_objects */ +FLEXTGL_EXPORT void(APIENTRY *flextglActiveShaderProgramEXT)(GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglBindProgramPipelineEXT)(GLuint) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShaderProgramvEXT)(GLenum, GLsizei, const GLchar **) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgramPipelinesEXT)(GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGenProgramPipelinesEXT)(GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineInfoLogEXT)(GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineivEXT)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgramPipelineEXT)(GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramParameteriEXT)(GLuint, GLenum, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fEXT)(GLuint, GLint, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iEXT)(GLuint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uiEXT)(GLuint, GLint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fEXT)(GLuint, GLint, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iEXT)(GLuint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uiEXT)(GLuint, GLint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iEXT)(GLuint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fvEXT)(GLuint, GLint, GLsizei, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iEXT)(GLuint, GLint, GLint, GLint, GLint, GLint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ivEXT)(GLuint, GLint, GLsizei, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uivEXT)(GLuint, GLint, GLsizei, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStagesEXT)(GLuint, GLbitfield, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipelineEXT)(GLuint) = nullptr; + +/* GL_EXT_tessellation_shader */ +FLEXTGL_EXPORT void(APIENTRY *flextglPatchParameteriEXT)(GLenum, GLint) = nullptr; + +/* GL_EXT_texture_border_clamp */ +FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIivEXT)(GLuint, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIuivEXT)(GLuint, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIivEXT)(GLenum, GLenum, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIuivEXT)(GLenum, GLenum, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIivEXT)(GLuint, GLenum, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIuivEXT)(GLuint, GLenum, const GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIivEXT)(GLenum, GLenum, const GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIuivEXT)(GLenum, GLenum, const GLuint *) = nullptr; + +/* GL_EXT_texture_buffer */ +FLEXTGL_EXPORT void(APIENTRY *flextglTexBufferEXT)(GLenum, GLenum, GLuint) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglTexBufferRangeEXT)(GLenum, GLenum, GLuint, GLintptr, GLsizeiptr) = nullptr; + +/* GL_KHR_blend_equation_advanced */ +FLEXTGL_EXPORT void(APIENTRY *flextglBlendBarrierKHR)(void) = nullptr; + +/* GL_KHR_debug */ +FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageCallbackKHR)(GLDEBUGPROCKHR, const void *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageControlKHR)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageInsertKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetDebugMessageLogKHR)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelKHR)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectPtrLabelKHR)(const void *, GLsizei, GLsizei *, GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetPointervKHR)(GLenum, void **) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglObjectLabelKHR)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglObjectPtrLabelKHR)(const void *, GLsizei, const GLchar *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPopDebugGroupKHR)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglPushDebugGroupKHR)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; + +/* GL_KHR_robustness */ +FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusKHR)(void) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvKHR)(GLuint, GLint, GLsizei, GLfloat *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivKHR)(GLuint, GLint, GLsizei, GLint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformuivKHR)(GLuint, GLint, GLsizei, GLuint *) = nullptr; +FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsKHR)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *) = nullptr; + +/* GL_NV_polygon_mode */ +FLEXTGL_EXPORT void(APIENTRY *flextglPolygonModeNV)(GLenum, GLenum) = nullptr; + +/* GL_OES_mapbuffer */ +FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferPointervOES)(GLenum, GLenum, void **) = nullptr; +FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferOES)(GLenum, GLenum) = nullptr; +FLEXTGL_EXPORT GLboolean(APIENTRY *flextglUnmapBufferOES)(GLenum) = nullptr; + +/* GL_OES_sample_shading */ +FLEXTGL_EXPORT void(APIENTRY *flextglMinSampleShadingOES)(GLfloat) = nullptr; + +/* GL_OES_texture_storage_multisample_2d_array */ +FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3DMultisampleOES)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean) = nullptr; + +#ifdef __cplusplus +} +#endif diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.cpp.template b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.cpp.template new file mode 100644 index 000000000..dfc149e94 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.cpp.template @@ -0,0 +1,22 @@ +@require(passthru, functions, enums, options, version, extensions) +#include "flextGLWindowsDesktop.h" + +#ifdef __cplusplus +extern "C" { +#endif +@for category,funcs in functions: +@if funcs: + +/* GL_@category */ +@for f in funcs: + @if f.name not in ['BlendFunc', 'Clear', 'ClearColor', 'ClearDepth', 'ClearStencil', 'ColorMask', 'CullFace', 'DepthFunc', 'DepthMask', 'DepthRange', 'Disable', 'DrawBuffer', 'Enable', 'Finish', 'Flush', 'FrontFace', 'GetBooleanv', 'GetDoublev', 'GetError', 'GetFloatv', 'GetIntegerv', 'GetString', 'GetTexImage', 'GetTexLevelParameterfv', 'GetTexLevelParameteriv', 'GetTexParameterfv', 'GetTexParameteriv', 'Hint', 'IsEnabled', 'LineWidth', 'LogicOp', 'PixelStoref', 'PixelStorei', 'PointSize', 'PolygonMode', 'ReadBuffer', 'ReadPixels', 'Scissor', 'StencilFunc', 'StencilMask', 'StencilOp', 'TexImage1D', 'TexImage2D', 'TexParameterf', 'TexParameterfv', 'TexParameteri', 'TexParameteriv', 'Viewport', 'BindTexture', 'CopyTexImage1D', 'CopyTexImage2D', 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'DeleteTextures', 'DrawArrays', 'DrawElements', 'GenTextures', 'IsTexture', 'PolygonOffset', 'TexSubImage1D', 'TexSubImage2D']: +FLEXTGL_EXPORT @f.returntype\ +(APIENTRY *flextgl@f.name)(@f.param_type_list_string()) = nullptr; + @end +@end +@end +@end + +#ifdef __cplusplus +} +#endif diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.h b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.h new file mode 100644 index 000000000..b0d5cdf1c --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.h @@ -0,0 +1,2237 @@ +#ifndef _flextgl_h_ +#define _flextgl_h_ + +#include + +#include "Magnum/configure.h" + +/* Defensive include guards */ + +#if defined(__gl_h_) || defined(__gl2_h_) || defined(__gl3_h_) || defined(__gl31_h_) +#error Attempt to include auto-generated header after including gl3.h +#endif +#if defined(__gl2ext_h_) || defined(__gl3ext_h_) +#error Attempt to include auto-generated header after including gl3ext.h +#endif +#if defined(__gl2platform_h_) || defined(__gl3platform_h_) +#error Attempt to include auto-generated header after including gl3platform.h +#endif + +#define __gl_h_ +#define __gl2_h_ +#define __gl3_h_ +#define __gl31_h_ +#define __gl2ext_h_ +#define __gl3ext_h_ +#define __gl2platform_h_ +#define __gl3platform_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +void flextGLInit(); + +/* Function declaration macros */ + +#ifndef MAGNUM_BUILD_STATIC + #ifdef FlextGL_EXPORTS + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_STATIC +#endif + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define APIENTRY WINAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/* Data types */ + +#include +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef short GLshort; +typedef int GLint; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef int GLsizei; +typedef char GLchar; +typedef unsigned short GLhalf; +typedef struct __GLsync *GLsync; +typedef void (APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef khronos_int8_t GLbyte; +typedef khronos_uint8_t GLubyte; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; + +/* Enums */ + +/* GL_ES_VERSION_2_0 */ + +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_NONE 0 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + +/* GL_ES_VERSION_3_0 */ + +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF + +/* GL_ES_VERSION_3_1 */ + +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_NAME_LENGTH 0x92F9 +#define GL_TYPE 0x92FA +#define GL_ARRAY_SIZE 0x92FB +#define GL_OFFSET 0x92FC +#define GL_BLOCK_INDEX 0x92FD +#define GL_ARRAY_STRIDE 0x92FE +#define GL_MATRIX_STRIDE 0x92FF +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_LOCATION 0x930E +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_STENCIL_INDEX 0x1901 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 + +/* GL_APPLE_texture_format_BGRA8888 */ + +#define GL_BGRA_EXT 0x80E1 +#define GL_BGRA8_EXT 0x93A1 + +/* GL_ARM_shader_framebuffer_fetch */ + +#define GL_FETCH_PER_SAMPLE_ARM 0x8F65 +#define GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66 + +/* GL_EXT_texture_filter_anisotropic */ + +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + +/* GL_EXT_texture_format_BGRA8888 */ + +#define GL_BGRA_EXT 0x80E1 + +/* GL_EXT_read_format_bgra */ + +#define GL_BGRA_EXT 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 + +/* GL_EXT_debug_label */ + +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 +#define GL_SAMPLER 0x82E6 +#define GL_TRANSFORM_FEEDBACK 0x8E22 + +/* GL_EXT_shader_framebuffer_fetch */ + +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 + +/* GL_EXT_disjoint_timer_query */ + +#define GL_QUERY_COUNTER_BITS_EXT 0x8864 +#define GL_CURRENT_QUERY_EXT 0x8865 +#define GL_QUERY_RESULT_EXT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 +#define GL_TIME_ELAPSED_EXT 0x88BF +#define GL_TIMESTAMP_EXT 0x8E28 +#define GL_GPU_DISJOINT_EXT 0x8FBB + +/* GL_EXT_texture_sRGB_decode */ + +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A + +/* GL_EXT_sRGB_write_control */ + +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 + +/* GL_EXT_texture_compression_s3tc */ + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +/* GL_EXT_draw_buffers_indexed */ + +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_BLEND 0x0BE2 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_SRC_ALPHA_SATURATE 0x0308 + +/* GL_EXT_geometry_shader */ + +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_SHADER_BIT_EXT 0x00000004 +#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916 +#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917 +#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918 +#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F +#define GL_LAYER_PROVOKING_VERTEX_EXT 0x825E +#define GL_LINES_ADJACENCY_EXT 0x000A +#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B +#define GL_TRIANGLES_ADJACENCY_EXT 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5 +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7 +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_UNDEFINED_VERTEX_EXT 0x8260 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312 +#define GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309 + +/* GL_EXT_tessellation_shader */ + +#define GL_PATCHES_EXT 0x000E +#define GL_PATCH_VERTICES_EXT 0x8E72 +#define GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75 +#define GL_TESS_GEN_MODE_EXT 0x8E76 +#define GL_TESS_GEN_SPACING_EXT 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER_EXT 0x8E78 +#define GL_TESS_GEN_POINT_MODE_EXT 0x8E79 +#define GL_TRIANGLES 0x0004 +#define GL_ISOLINES_EXT 0x8E7A +#define GL_QUADS_EXT 0x0007 +#define GL_EQUAL 0x0202 +#define GL_FRACTIONAL_ODD_EXT 0x8E7B +#define GL_FRACTIONAL_EVEN_EXT 0x8E7C +#define GL_CCW 0x0901 +#define GL_CW 0x0900 +#define GL_MAX_PATCH_VERTICES_EXT 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL_EXT 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS_EXT 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4 +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_IS_PER_PATCH_EXT 0x92E7 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308 +#define GL_TESS_CONTROL_SHADER_EXT 0x8E88 +#define GL_TESS_EVALUATION_SHADER_EXT 0x8E87 +#define GL_TESS_CONTROL_SHADER_BIT_EXT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010 + +/* GL_EXT_texture_border_clamp */ + +#define GL_TEXTURE_BORDER_COLOR_EXT 0x1004 +#define GL_CLAMP_TO_BORDER_EXT 0x812D + +/* GL_EXT_texture_buffer */ + +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_TEXTURE_BUFFER_BINDING_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_TEXTURE_BUFFER_OFFSET_EXT 0x919D +#define GL_TEXTURE_BUFFER_SIZE_EXT 0x919E + +/* GL_EXT_texture_cube_map_array */ + +#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A +#define GL_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A + +/* GL_EXT_primitive_bounding_box */ + +#define GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE + +/* GL_EXT_separate_shader_objects */ + +#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 +#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE_EXT 0x8258 +#define GL_ACTIVE_PROGRAM_EXT 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A + +/* GL_EXT_multisampled_render_to_texture */ + +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 + +/* GL_EXT_robustness */ + +#define GL_NO_ERROR 0 +#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 +#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 +#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 +#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 +#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 + +/* GL_KHR_texture_compression_astc_ldr */ + +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD + +/* GL_KHR_texture_compression_astc_hdr */ + +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD + +/* GL_KHR_debug */ + +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245 +#define GL_DEBUG_SOURCE_API_KHR 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A +#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B +#define GL_DEBUG_TYPE_ERROR_KHR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250 +#define GL_DEBUG_TYPE_OTHER_KHR 0x8251 +#define GL_DEBUG_TYPE_MARKER_KHR 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D +#define GL_BUFFER_KHR 0x82E0 +#define GL_SHADER_KHR 0x82E1 +#define GL_PROGRAM_KHR 0x82E2 +#define GL_VERTEX_ARRAY_KHR 0x8074 +#define GL_QUERY_KHR 0x82E3 +#define GL_PROGRAM_PIPELINE_KHR 0x82E4 +#define GL_SAMPLER_KHR 0x82E6 +#define GL_MAX_LABEL_LENGTH_KHR 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147 +#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148 +#define GL_DEBUG_OUTPUT_KHR 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002 +#define GL_STACK_OVERFLOW_KHR 0x0503 +#define GL_STACK_UNDERFLOW_KHR 0x0504 + +/* GL_KHR_blend_equation_advanced */ + +#define GL_MULTIPLY_KHR 0x9294 +#define GL_SCREEN_KHR 0x9295 +#define GL_OVERLAY_KHR 0x9296 +#define GL_DARKEN_KHR 0x9297 +#define GL_LIGHTEN_KHR 0x9298 +#define GL_COLORDODGE_KHR 0x9299 +#define GL_COLORBURN_KHR 0x929A +#define GL_HARDLIGHT_KHR 0x929B +#define GL_SOFTLIGHT_KHR 0x929C +#define GL_DIFFERENCE_KHR 0x929E +#define GL_EXCLUSION_KHR 0x92A0 +#define GL_HSL_HUE_KHR 0x92AD +#define GL_HSL_SATURATION_KHR 0x92AE +#define GL_HSL_COLOR_KHR 0x92AF +#define GL_HSL_LUMINOSITY_KHR 0x92B0 + +/* GL_KHR_blend_equation_advanced_coherent */ + +#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285 + +/* GL_KHR_robustness */ + +#define GL_NO_ERROR 0 +#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3 +#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252 +#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256 +#define GL_NO_RESET_NOTIFICATION_KHR 0x8261 +#define GL_CONTEXT_LOST_KHR 0x0507 + +/* GL_KHR_context_flush_control */ + +#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC +#define GL_NONE 0 + +/* GL_KHR_no_error */ + +#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008 + +/* GL_NV_texture_border_clamp */ + +#define GL_TEXTURE_BORDER_COLOR_NV 0x1004 +#define GL_CLAMP_TO_BORDER_NV 0x812D + +/* GL_NV_polygon_mode */ + +#define GL_POLYGON_MODE_NV 0x0B40 +#define GL_POLYGON_OFFSET_POINT_NV 0x2A01 +#define GL_POLYGON_OFFSET_LINE_NV 0x2A02 +#define GL_POINT_NV 0x1B00 +#define GL_LINE_NV 0x1B01 +#define GL_FILL_NV 0x1B02 + +/* GL_OES_depth32 */ + +#define GL_DEPTH_COMPONENT32_OES 0x81A7 + +/* GL_OES_mapbuffer */ + +#define GL_WRITE_ONLY_OES 0x88B9 +#define GL_BUFFER_ACCESS_OES 0x88BB +#define GL_BUFFER_MAPPED_OES 0x88BC +#define GL_BUFFER_MAP_POINTER_OES 0x88BD + +/* GL_OES_stencil1 */ + +#define GL_STENCIL_INDEX1_OES 0x8D46 + +/* GL_OES_stencil4 */ + +#define GL_STENCIL_INDEX4_OES 0x8D47 + +/* GL_OES_sample_shading */ + +#define GL_SAMPLE_SHADING_OES 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE_OES 0x8C37 + +/* GL_OES_shader_multisample_interpolation */ + +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D + +/* GL_OES_texture_stencil8 */ + +#define GL_STENCIL_INDEX_OES 0x1901 +#define GL_STENCIL_INDEX8_OES 0x8D48 + +/* GL_OES_texture_storage_multisample_2d_array */ + +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D + +/* Function prototypes */ + +/* GL_ES_VERSION_2_0 */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglActiveTexture)(GLenum); +#define glActiveTexture flextglActiveTexture +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglAttachShader)(GLuint, GLuint); +#define glAttachShader flextglAttachShader +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindAttribLocation)(GLuint, GLuint, const GLchar *); +#define glBindAttribLocation flextglBindAttribLocation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindBuffer)(GLenum, GLuint); +#define glBindBuffer flextglBindBuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindFramebuffer)(GLenum, GLuint); +#define glBindFramebuffer flextglBindFramebuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindRenderbuffer)(GLenum, GLuint); +#define glBindRenderbuffer flextglBindRenderbuffer +GLAPI FLEXTGL_EXPORT void APIENTRY glBindTexture(GLenum, GLuint); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendColor)(GLfloat, GLfloat, GLfloat, GLfloat); +#define glBlendColor flextglBlendColor +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquation)(GLenum); +#define glBlendEquation flextglBlendEquation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparate)(GLenum, GLenum); +#define glBlendEquationSeparate flextglBlendEquationSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glBlendFunc(GLenum, GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparate)(GLenum, GLenum, GLenum, GLenum); +#define glBlendFuncSeparate flextglBlendFuncSeparate +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBufferData)(GLenum, GLsizeiptr, const void *, GLenum); +#define glBufferData flextglBufferData +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBufferSubData)(GLenum, GLintptr, GLsizeiptr, const void *); +#define glBufferSubData flextglBufferSubData +GLAPI FLEXTGL_EXPORT GLenum(APIENTRY *flextglCheckFramebufferStatus)(GLenum); +#define glCheckFramebufferStatus flextglCheckFramebufferStatus +GLAPI FLEXTGL_EXPORT void APIENTRY glClear(GLbitfield); +GLAPI FLEXTGL_EXPORT void APIENTRY glClearColor(GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglClearDepthf)(GLfloat); +#define glClearDepthf flextglClearDepthf +GLAPI FLEXTGL_EXPORT void APIENTRY glClearStencil(GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glColorMask(GLboolean, GLboolean, GLboolean, GLboolean); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompileShader)(GLuint); +#define glCompileShader flextglCompileShader +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage2D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *); +#define glCompressedTexImage2D flextglCompressedTexImage2D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *); +#define glCompressedTexSubImage2D flextglCompressedTexSubImage2D +GLAPI FLEXTGL_EXPORT void APIENTRY glCopyTexImage2D(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glCopyTexSubImage2D(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateProgram)(void); +#define glCreateProgram flextglCreateProgram +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShader)(GLenum); +#define glCreateShader flextglCreateShader +GLAPI FLEXTGL_EXPORT void APIENTRY glCullFace(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteBuffers)(GLsizei, const GLuint *); +#define glDeleteBuffers flextglDeleteBuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteFramebuffers)(GLsizei, const GLuint *); +#define glDeleteFramebuffers flextglDeleteFramebuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgram)(GLuint); +#define glDeleteProgram flextglDeleteProgram +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteRenderbuffers)(GLsizei, const GLuint *); +#define glDeleteRenderbuffers flextglDeleteRenderbuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteShader)(GLuint); +#define glDeleteShader flextglDeleteShader +GLAPI FLEXTGL_EXPORT void APIENTRY glDeleteTextures(GLsizei, const GLuint *); +GLAPI FLEXTGL_EXPORT void APIENTRY glDepthFunc(GLenum); +GLAPI FLEXTGL_EXPORT void APIENTRY glDepthMask(GLboolean); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDepthRangef)(GLfloat, GLfloat); +#define glDepthRangef flextglDepthRangef +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDetachShader)(GLuint, GLuint); +#define glDetachShader flextglDetachShader +GLAPI FLEXTGL_EXPORT void APIENTRY glDisable(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDisableVertexAttribArray)(GLuint); +#define glDisableVertexAttribArray flextglDisableVertexAttribArray +GLAPI FLEXTGL_EXPORT void APIENTRY glDrawArrays(GLenum, GLint, GLsizei); +GLAPI FLEXTGL_EXPORT void APIENTRY glDrawElements(GLenum, GLsizei, GLenum, const void *); +GLAPI FLEXTGL_EXPORT void APIENTRY glEnable(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEnableVertexAttribArray)(GLuint); +#define glEnableVertexAttribArray flextglEnableVertexAttribArray +GLAPI FLEXTGL_EXPORT void APIENTRY glFinish(void); +GLAPI FLEXTGL_EXPORT void APIENTRY glFlush(void); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint); +#define glFramebufferRenderbuffer flextglFramebufferRenderbuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint, GLint); +#define glFramebufferTexture2D flextglFramebufferTexture2D +GLAPI FLEXTGL_EXPORT void APIENTRY glFrontFace(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenBuffers)(GLsizei, GLuint *); +#define glGenBuffers flextglGenBuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenFramebuffers)(GLsizei, GLuint *); +#define glGenFramebuffers flextglGenFramebuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenRenderbuffers)(GLsizei, GLuint *); +#define glGenRenderbuffers flextglGenRenderbuffers +GLAPI FLEXTGL_EXPORT void APIENTRY glGenTextures(GLsizei, GLuint *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenerateMipmap)(GLenum); +#define glGenerateMipmap flextglGenerateMipmap +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveAttrib)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +#define glGetActiveAttrib flextglGetActiveAttrib +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniform)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +#define glGetActiveUniform flextglGetActiveUniform +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetAttachedShaders)(GLuint, GLsizei, GLsizei *, GLuint *); +#define glGetAttachedShaders flextglGetAttachedShaders +GLAPI FLEXTGL_EXPORT GLint(APIENTRY *flextglGetAttribLocation)(GLuint, const GLchar *); +#define glGetAttribLocation flextglGetAttribLocation +GLAPI FLEXTGL_EXPORT void APIENTRY glGetBooleanv(GLenum, GLboolean *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferParameteriv)(GLenum, GLenum, GLint *); +#define glGetBufferParameteriv flextglGetBufferParameteriv +GLAPI FLEXTGL_EXPORT GLenum APIENTRY glGetError(void); +GLAPI FLEXTGL_EXPORT void APIENTRY glGetFloatv(GLenum, GLfloat *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetFramebufferAttachmentParameteriv)(GLenum, GLenum, GLenum, GLint *); +#define glGetFramebufferAttachmentParameteriv flextglGetFramebufferAttachmentParameteriv +GLAPI FLEXTGL_EXPORT void APIENTRY glGetIntegerv(GLenum, GLint *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetProgramInfoLog flextglGetProgramInfoLog +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramiv)(GLuint, GLenum, GLint *); +#define glGetProgramiv flextglGetProgramiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetRenderbufferParameteriv)(GLenum, GLenum, GLint *); +#define glGetRenderbufferParameteriv flextglGetRenderbufferParameteriv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetShaderInfoLog flextglGetShaderInfoLog +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderPrecisionFormat)(GLenum, GLenum, GLint *, GLint *); +#define glGetShaderPrecisionFormat flextglGetShaderPrecisionFormat +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderSource)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetShaderSource flextglGetShaderSource +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetShaderiv)(GLuint, GLenum, GLint *); +#define glGetShaderiv flextglGetShaderiv +GLAPI FLEXTGL_EXPORT const GLubyte * APIENTRY glGetString(GLenum); +GLAPI FLEXTGL_EXPORT void APIENTRY glGetTexParameterfv(GLenum, GLenum, GLfloat *); +GLAPI FLEXTGL_EXPORT void APIENTRY glGetTexParameteriv(GLenum, GLenum, GLint *); +GLAPI FLEXTGL_EXPORT GLint(APIENTRY *flextglGetUniformLocation)(GLuint, const GLchar *); +#define glGetUniformLocation flextglGetUniformLocation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformfv)(GLuint, GLint, GLfloat *); +#define glGetUniformfv flextglGetUniformfv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformiv)(GLuint, GLint, GLint *); +#define glGetUniformiv flextglGetUniformiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribPointerv)(GLuint, GLenum, void **); +#define glGetVertexAttribPointerv flextglGetVertexAttribPointerv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribfv)(GLuint, GLenum, GLfloat *); +#define glGetVertexAttribfv flextglGetVertexAttribfv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribiv)(GLuint, GLenum, GLint *); +#define glGetVertexAttribiv flextglGetVertexAttribiv +GLAPI FLEXTGL_EXPORT void APIENTRY glHint(GLenum, GLenum); +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsBuffer)(GLuint); +#define glIsBuffer flextglIsBuffer +GLAPI FLEXTGL_EXPORT GLboolean APIENTRY glIsEnabled(GLenum); +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsFramebuffer)(GLuint); +#define glIsFramebuffer flextglIsFramebuffer +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgram)(GLuint); +#define glIsProgram flextglIsProgram +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsRenderbuffer)(GLuint); +#define glIsRenderbuffer flextglIsRenderbuffer +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsShader)(GLuint); +#define glIsShader flextglIsShader +GLAPI FLEXTGL_EXPORT GLboolean APIENTRY glIsTexture(GLuint); +GLAPI FLEXTGL_EXPORT void APIENTRY glLineWidth(GLfloat); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglLinkProgram)(GLuint); +#define glLinkProgram flextglLinkProgram +GLAPI FLEXTGL_EXPORT void APIENTRY glPixelStorei(GLenum, GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glPolygonOffset(GLfloat, GLfloat); +GLAPI FLEXTGL_EXPORT void APIENTRY glReadPixels(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, void *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglReleaseShaderCompiler)(void); +#define glReleaseShaderCompiler flextglReleaseShaderCompiler +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorage flextglRenderbufferStorage +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSampleCoverage)(GLfloat, GLboolean); +#define glSampleCoverage flextglSampleCoverage +GLAPI FLEXTGL_EXPORT void APIENTRY glScissor(GLint, GLint, GLsizei, GLsizei); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglShaderBinary)(GLsizei, const GLuint *, GLenum, const void *, GLsizei); +#define glShaderBinary flextglShaderBinary +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglShaderSource)(GLuint, GLsizei, const GLchar *const*, const GLint *); +#define glShaderSource flextglShaderSource +GLAPI FLEXTGL_EXPORT void APIENTRY glStencilFunc(GLenum, GLint, GLuint); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint); +#define glStencilFuncSeparate flextglStencilFuncSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glStencilMask(GLuint); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglStencilMaskSeparate)(GLenum, GLuint); +#define glStencilMaskSeparate flextglStencilMaskSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glStencilOp(GLenum, GLenum, GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum); +#define glStencilOpSeparate flextglStencilOpSeparate +GLAPI FLEXTGL_EXPORT void APIENTRY glTexImage2D(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameterf(GLenum, GLenum, GLfloat); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameterfv(GLenum, GLenum, const GLfloat *); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameteri(GLenum, GLenum, GLint); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexParameteriv(GLenum, GLenum, const GLint *); +GLAPI FLEXTGL_EXPORT void APIENTRY glTexSubImage2D(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1f)(GLint, GLfloat); +#define glUniform1f flextglUniform1f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1fv)(GLint, GLsizei, const GLfloat *); +#define glUniform1fv flextglUniform1fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1i)(GLint, GLint); +#define glUniform1i flextglUniform1i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1iv)(GLint, GLsizei, const GLint *); +#define glUniform1iv flextglUniform1iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2f)(GLint, GLfloat, GLfloat); +#define glUniform2f flextglUniform2f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2fv)(GLint, GLsizei, const GLfloat *); +#define glUniform2fv flextglUniform2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2i)(GLint, GLint, GLint); +#define glUniform2i flextglUniform2i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2iv)(GLint, GLsizei, const GLint *); +#define glUniform2iv flextglUniform2iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3f)(GLint, GLfloat, GLfloat, GLfloat); +#define glUniform3f flextglUniform3f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3fv)(GLint, GLsizei, const GLfloat *); +#define glUniform3fv flextglUniform3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3i)(GLint, GLint, GLint, GLint); +#define glUniform3i flextglUniform3i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3iv)(GLint, GLsizei, const GLint *); +#define glUniform3iv flextglUniform3iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat); +#define glUniform4f flextglUniform4f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4fv)(GLint, GLsizei, const GLfloat *); +#define glUniform4fv flextglUniform4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4i)(GLint, GLint, GLint, GLint, GLint); +#define glUniform4i flextglUniform4i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4iv)(GLint, GLsizei, const GLint *); +#define glUniform4iv flextglUniform4iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix2fv flextglUniformMatrix2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix3fv flextglUniformMatrix3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix4fv flextglUniformMatrix4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUseProgram)(GLuint); +#define glUseProgram flextglUseProgram +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgram)(GLuint); +#define glValidateProgram flextglValidateProgram +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1f)(GLuint, GLfloat); +#define glVertexAttrib1f flextglVertexAttrib1f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib1fv)(GLuint, const GLfloat *); +#define glVertexAttrib1fv flextglVertexAttrib1fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2f)(GLuint, GLfloat, GLfloat); +#define glVertexAttrib2f flextglVertexAttrib2f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib2fv)(GLuint, const GLfloat *); +#define glVertexAttrib2fv flextglVertexAttrib2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3f)(GLuint, GLfloat, GLfloat, GLfloat); +#define glVertexAttrib3f flextglVertexAttrib3f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib3fv)(GLuint, const GLfloat *); +#define glVertexAttrib3fv flextglVertexAttrib3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4f)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +#define glVertexAttrib4f flextglVertexAttrib4f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttrib4fv)(GLuint, const GLfloat *); +#define glVertexAttrib4fv flextglVertexAttrib4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *); +#define glVertexAttribPointer flextglVertexAttribPointer +GLAPI FLEXTGL_EXPORT void APIENTRY glViewport(GLint, GLint, GLsizei, GLsizei); + +/* GL_ES_VERSION_3_0 */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBeginQuery)(GLenum, GLuint); +#define glBeginQuery flextglBeginQuery +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBeginTransformFeedback)(GLenum); +#define glBeginTransformFeedback flextglBeginTransformFeedback +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindBufferBase)(GLenum, GLuint, GLuint); +#define glBindBufferBase flextglBindBufferBase +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindBufferRange)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr); +#define glBindBufferRange flextglBindBufferRange +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindSampler)(GLuint, GLuint); +#define glBindSampler flextglBindSampler +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindTransformFeedback)(GLenum, GLuint); +#define glBindTransformFeedback flextglBindTransformFeedback +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindVertexArray)(GLuint); +#define glBindVertexArray flextglBindVertexArray +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlitFramebuffer)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); +#define glBlitFramebuffer flextglBlitFramebuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferfi)(GLenum, GLint, GLfloat, GLint); +#define glClearBufferfi flextglClearBufferfi +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferfv)(GLenum, GLint, const GLfloat *); +#define glClearBufferfv flextglClearBufferfv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferiv)(GLenum, GLint, const GLint *); +#define glClearBufferiv flextglClearBufferiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglClearBufferuiv)(GLenum, GLint, const GLuint *); +#define glClearBufferuiv flextglClearBufferuiv +GLAPI FLEXTGL_EXPORT GLenum(APIENTRY *flextglClientWaitSync)(GLsync, GLbitfield, GLuint64); +#define glClientWaitSync flextglClientWaitSync +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexImage3D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const void *); +#define glCompressedTexImage3D flextglCompressedTexImage3D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCompressedTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *); +#define glCompressedTexSubImage3D flextglCompressedTexSubImage3D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr); +#define glCopyBufferSubData flextglCopyBufferSubData +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCopyTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#define glCopyTexSubImage3D flextglCopyTexSubImage3D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteQueries)(GLsizei, const GLuint *); +#define glDeleteQueries flextglDeleteQueries +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteSamplers)(GLsizei, const GLuint *); +#define glDeleteSamplers flextglDeleteSamplers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteSync)(GLsync); +#define glDeleteSync flextglDeleteSync +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteTransformFeedbacks)(GLsizei, const GLuint *); +#define glDeleteTransformFeedbacks flextglDeleteTransformFeedbacks +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteVertexArrays)(GLsizei, const GLuint *); +#define glDeleteVertexArrays flextglDeleteVertexArrays +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysInstanced)(GLenum, GLint, GLsizei, GLsizei); +#define glDrawArraysInstanced flextglDrawArraysInstanced +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawBuffers)(GLsizei, const GLenum *); +#define glDrawBuffers flextglDrawBuffers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsInstanced)(GLenum, GLsizei, GLenum, const void *, GLsizei); +#define glDrawElementsInstanced flextglDrawElementsInstanced +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawRangeElements)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void *); +#define glDrawRangeElements flextglDrawRangeElements +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEndQuery)(GLenum); +#define glEndQuery flextglEndQuery +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEndTransformFeedback)(void); +#define glEndTransformFeedback flextglEndTransformFeedback +GLAPI FLEXTGL_EXPORT GLsync(APIENTRY *flextglFenceSync)(GLenum, GLbitfield); +#define glFenceSync flextglFenceSync +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFlushMappedBufferRange)(GLenum, GLintptr, GLsizeiptr); +#define glFlushMappedBufferRange flextglFlushMappedBufferRange +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTextureLayer)(GLenum, GLenum, GLuint, GLint, GLint); +#define glFramebufferTextureLayer flextglFramebufferTextureLayer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenQueries)(GLsizei, GLuint *); +#define glGenQueries flextglGenQueries +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenSamplers)(GLsizei, GLuint *); +#define glGenSamplers flextglGenSamplers +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenTransformFeedbacks)(GLsizei, GLuint *); +#define glGenTransformFeedbacks flextglGenTransformFeedbacks +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenVertexArrays)(GLsizei, GLuint *); +#define glGenVertexArrays flextglGenVertexArrays +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniformBlockName)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetActiveUniformBlockName flextglGetActiveUniformBlockName +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniformBlockiv)(GLuint, GLuint, GLenum, GLint *); +#define glGetActiveUniformBlockiv flextglGetActiveUniformBlockiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetActiveUniformsiv)(GLuint, GLsizei, const GLuint *, GLenum, GLint *); +#define glGetActiveUniformsiv flextglGetActiveUniformsiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferParameteri64v)(GLenum, GLenum, GLint64 *); +#define glGetBufferParameteri64v flextglGetBufferParameteri64v +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferPointerv)(GLenum, GLenum, void **); +#define glGetBufferPointerv flextglGetBufferPointerv +GLAPI FLEXTGL_EXPORT GLint(APIENTRY *flextglGetFragDataLocation)(GLuint, const GLchar *); +#define glGetFragDataLocation flextglGetFragDataLocation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetInteger64i_v)(GLenum, GLuint, GLint64 *); +#define glGetInteger64i_v flextglGetInteger64i_v +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetInteger64v)(GLenum, GLint64 *); +#define glGetInteger64v flextglGetInteger64v +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetIntegeri_v)(GLenum, GLuint, GLint *); +#define glGetIntegeri_v flextglGetIntegeri_v +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetInternalformativ)(GLenum, GLenum, GLenum, GLsizei, GLint *); +#define glGetInternalformativ flextglGetInternalformativ +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramBinary)(GLuint, GLsizei, GLsizei *, GLenum *, void *); +#define glGetProgramBinary flextglGetProgramBinary +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectuiv)(GLuint, GLenum, GLuint *); +#define glGetQueryObjectuiv flextglGetQueryObjectuiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryiv)(GLenum, GLenum, GLint *); +#define glGetQueryiv flextglGetQueryiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterfv)(GLuint, GLenum, GLfloat *); +#define glGetSamplerParameterfv flextglGetSamplerParameterfv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameteriv)(GLuint, GLenum, GLint *); +#define glGetSamplerParameteriv flextglGetSamplerParameteriv +GLAPI FLEXTGL_EXPORT const GLubyte *(APIENTRY *flextglGetStringi)(GLenum, GLuint); +#define glGetStringi flextglGetStringi +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetSynciv)(GLsync, GLenum, GLsizei, GLsizei *, GLint *); +#define glGetSynciv flextglGetSynciv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetTransformFeedbackVarying)(GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); +#define glGetTransformFeedbackVarying flextglGetTransformFeedbackVarying +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetUniformBlockIndex)(GLuint, const GLchar *); +#define glGetUniformBlockIndex flextglGetUniformBlockIndex +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformIndices)(GLuint, GLsizei, const GLchar *const*, GLuint *); +#define glGetUniformIndices flextglGetUniformIndices +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetUniformuiv)(GLuint, GLint, GLuint *); +#define glGetUniformuiv flextglGetUniformuiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribIiv)(GLuint, GLenum, GLint *); +#define glGetVertexAttribIiv flextglGetVertexAttribIiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetVertexAttribIuiv)(GLuint, GLenum, GLuint *); +#define glGetVertexAttribIuiv flextglGetVertexAttribIuiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglInvalidateFramebuffer)(GLenum, GLsizei, const GLenum *); +#define glInvalidateFramebuffer flextglInvalidateFramebuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglInvalidateSubFramebuffer)(GLenum, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei); +#define glInvalidateSubFramebuffer flextglInvalidateSubFramebuffer +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsQuery)(GLuint); +#define glIsQuery flextglIsQuery +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsSampler)(GLuint); +#define glIsSampler flextglIsSampler +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsSync)(GLsync); +#define glIsSync flextglIsSync +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsTransformFeedback)(GLuint); +#define glIsTransformFeedback flextglIsTransformFeedback +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsVertexArray)(GLuint); +#define glIsVertexArray flextglIsVertexArray +GLAPI FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferRange)(GLenum, GLintptr, GLsizeiptr, GLbitfield); +#define glMapBufferRange flextglMapBufferRange +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPauseTransformFeedback)(void); +#define glPauseTransformFeedback flextglPauseTransformFeedback +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramBinary)(GLuint, GLenum, const void *, GLsizei); +#define glProgramBinary flextglProgramBinary +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramParameteri)(GLuint, GLenum, GLint); +#define glProgramParameteri flextglProgramParameteri +GLAPI FLEXTGL_EXPORT void APIENTRY glReadBuffer(GLenum); +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisample)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorageMultisample flextglRenderbufferStorageMultisample +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglResumeTransformFeedback)(void); +#define glResumeTransformFeedback flextglResumeTransformFeedback +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterf)(GLuint, GLenum, GLfloat); +#define glSamplerParameterf flextglSamplerParameterf +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterfv)(GLuint, GLenum, const GLfloat *); +#define glSamplerParameterfv flextglSamplerParameterfv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameteri)(GLuint, GLenum, GLint); +#define glSamplerParameteri flextglSamplerParameteri +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameteriv)(GLuint, GLenum, const GLint *); +#define glSamplerParameteriv flextglSamplerParameteriv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexImage3D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *); +#define glTexImage3D flextglTexImage3D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2D)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glTexStorage2D flextglTexStorage2D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3D)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei); +#define glTexStorage3D flextglTexStorage3D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *); +#define glTexSubImage3D flextglTexSubImage3D +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTransformFeedbackVaryings)(GLuint, GLsizei, const GLchar *const*, GLenum); +#define glTransformFeedbackVaryings flextglTransformFeedbackVaryings +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1ui)(GLint, GLuint); +#define glUniform1ui flextglUniform1ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform1uiv)(GLint, GLsizei, const GLuint *); +#define glUniform1uiv flextglUniform1uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2ui)(GLint, GLuint, GLuint); +#define glUniform2ui flextglUniform2ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform2uiv)(GLint, GLsizei, const GLuint *); +#define glUniform2uiv flextglUniform2uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3ui)(GLint, GLuint, GLuint, GLuint); +#define glUniform3ui flextglUniform3ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform3uiv)(GLint, GLsizei, const GLuint *); +#define glUniform3uiv flextglUniform3uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4ui)(GLint, GLuint, GLuint, GLuint, GLuint); +#define glUniform4ui flextglUniform4ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniform4uiv)(GLint, GLsizei, const GLuint *); +#define glUniform4uiv flextglUniform4uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformBlockBinding)(GLuint, GLuint, GLuint); +#define glUniformBlockBinding flextglUniformBlockBinding +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2x3fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix2x3fv flextglUniformMatrix2x3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix2x4fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix2x4fv flextglUniformMatrix2x4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3x2fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix3x2fv flextglUniformMatrix3x2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix3x4fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix3x4fv flextglUniformMatrix3x4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4x2fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix4x2fv flextglUniformMatrix4x2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUniformMatrix4x3fv)(GLint, GLsizei, GLboolean, const GLfloat *); +#define glUniformMatrix4x3fv flextglUniformMatrix4x3fv +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglUnmapBuffer)(GLenum); +#define glUnmapBuffer flextglUnmapBuffer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribDivisor)(GLuint, GLuint); +#define glVertexAttribDivisor flextglVertexAttribDivisor +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4i)(GLuint, GLint, GLint, GLint, GLint); +#define glVertexAttribI4i flextglVertexAttribI4i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4iv)(GLuint, const GLint *); +#define glVertexAttribI4iv flextglVertexAttribI4iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4ui)(GLuint, GLuint, GLuint, GLuint, GLuint); +#define glVertexAttribI4ui flextglVertexAttribI4ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribI4uiv)(GLuint, const GLuint *); +#define glVertexAttribI4uiv flextglVertexAttribI4uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribIPointer)(GLuint, GLint, GLenum, GLsizei, const void *); +#define glVertexAttribIPointer flextglVertexAttribIPointer +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglWaitSync)(GLsync, GLbitfield, GLuint64); +#define glWaitSync flextglWaitSync + +/* GL_ES_VERSION_3_1 */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglActiveShaderProgram)(GLuint, GLuint); +#define glActiveShaderProgram flextglActiveShaderProgram +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindImageTexture)(GLuint, GLuint, GLint, GLboolean, GLint, GLenum, GLenum); +#define glBindImageTexture flextglBindImageTexture +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindProgramPipeline)(GLuint); +#define glBindProgramPipeline flextglBindProgramPipeline +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindVertexBuffer)(GLuint, GLuint, GLintptr, GLsizei); +#define glBindVertexBuffer flextglBindVertexBuffer +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShaderProgramv)(GLenum, GLsizei, const GLchar *const*); +#define glCreateShaderProgramv flextglCreateShaderProgramv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgramPipelines)(GLsizei, const GLuint *); +#define glDeleteProgramPipelines flextglDeleteProgramPipelines +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDispatchCompute)(GLuint, GLuint, GLuint); +#define glDispatchCompute flextglDispatchCompute +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDispatchComputeIndirect)(GLintptr); +#define glDispatchComputeIndirect flextglDispatchComputeIndirect +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawArraysIndirect)(GLenum, const void *); +#define glDrawArraysIndirect flextglDrawArraysIndirect +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDrawElementsIndirect)(GLenum, GLenum, const void *); +#define glDrawElementsIndirect flextglDrawElementsIndirect +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferParameteri)(GLenum, GLenum, GLint); +#define glFramebufferParameteri flextglFramebufferParameteri +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenProgramPipelines)(GLsizei, GLuint *); +#define glGenProgramPipelines flextglGenProgramPipelines +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetBooleani_v)(GLenum, GLuint, GLboolean *); +#define glGetBooleani_v flextglGetBooleani_v +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetFramebufferParameteriv)(GLenum, GLenum, GLint *); +#define glGetFramebufferParameteriv flextglGetFramebufferParameteriv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetMultisamplefv)(GLenum, GLuint, GLfloat *); +#define glGetMultisamplefv flextglGetMultisamplefv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramInterfaceiv)(GLuint, GLenum, GLenum, GLint *); +#define glGetProgramInterfaceiv flextglGetProgramInterfaceiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetProgramPipelineInfoLog flextglGetProgramPipelineInfoLog +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineiv)(GLuint, GLenum, GLint *); +#define glGetProgramPipelineiv flextglGetProgramPipelineiv +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetProgramResourceIndex)(GLuint, GLenum, const GLchar *); +#define glGetProgramResourceIndex flextglGetProgramResourceIndex +GLAPI FLEXTGL_EXPORT GLint(APIENTRY *flextglGetProgramResourceLocation)(GLuint, GLenum, const GLchar *); +#define glGetProgramResourceLocation flextglGetProgramResourceLocation +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramResourceName)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetProgramResourceName flextglGetProgramResourceName +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramResourceiv)(GLuint, GLenum, GLuint, GLsizei, const GLenum *, GLsizei, GLsizei *, GLint *); +#define glGetProgramResourceiv flextglGetProgramResourceiv +GLAPI FLEXTGL_EXPORT void APIENTRY glGetTexLevelParameterfv(GLenum, GLint, GLenum, GLfloat *); +GLAPI FLEXTGL_EXPORT void APIENTRY glGetTexLevelParameteriv(GLenum, GLint, GLenum, GLint *); +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgramPipeline)(GLuint); +#define glIsProgramPipeline flextglIsProgramPipeline +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglMemoryBarrier)(GLbitfield); +#define glMemoryBarrier flextglMemoryBarrier +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglMemoryBarrierByRegion)(GLbitfield); +#define glMemoryBarrierByRegion flextglMemoryBarrierByRegion +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1f)(GLuint, GLint, GLfloat); +#define glProgramUniform1f flextglProgramUniform1f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fv)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform1fv flextglProgramUniform1fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1i)(GLuint, GLint, GLint); +#define glProgramUniform1i flextglProgramUniform1i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iv)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform1iv flextglProgramUniform1iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ui)(GLuint, GLint, GLuint); +#define glProgramUniform1ui flextglProgramUniform1ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uiv)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform1uiv flextglProgramUniform1uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2f)(GLuint, GLint, GLfloat, GLfloat); +#define glProgramUniform2f flextglProgramUniform2f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fv)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform2fv flextglProgramUniform2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2i)(GLuint, GLint, GLint, GLint); +#define glProgramUniform2i flextglProgramUniform2i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iv)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform2iv flextglProgramUniform2iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ui)(GLuint, GLint, GLuint, GLuint); +#define glProgramUniform2ui flextglProgramUniform2ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uiv)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform2uiv flextglProgramUniform2uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3f)(GLuint, GLint, GLfloat, GLfloat, GLfloat); +#define glProgramUniform3f flextglProgramUniform3f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fv)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform3fv flextglProgramUniform3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3i)(GLuint, GLint, GLint, GLint, GLint); +#define glProgramUniform3i flextglProgramUniform3i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iv)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform3iv flextglProgramUniform3iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ui)(GLuint, GLint, GLuint, GLuint, GLuint); +#define glProgramUniform3ui flextglProgramUniform3ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uiv)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform3uiv flextglProgramUniform3uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4f)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat); +#define glProgramUniform4f flextglProgramUniform4f +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fv)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform4fv flextglProgramUniform4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4i)(GLuint, GLint, GLint, GLint, GLint, GLint); +#define glProgramUniform4i flextglProgramUniform4i +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iv)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform4iv flextglProgramUniform4iv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ui)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint); +#define glProgramUniform4ui flextglProgramUniform4ui +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uiv)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform4uiv flextglProgramUniform4uiv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix2fv flextglProgramUniformMatrix2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x3fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix2x3fv flextglProgramUniformMatrix2x3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x4fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix2x4fv flextglProgramUniformMatrix2x4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix3fv flextglProgramUniformMatrix3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x2fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix3x2fv flextglProgramUniformMatrix3x2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x4fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix3x4fv flextglProgramUniformMatrix3x4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix4fv flextglProgramUniformMatrix4fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x2fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix4x2fv flextglProgramUniformMatrix4x2fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x3fv)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix4x3fv flextglProgramUniformMatrix4x3fv +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSampleMaski)(GLuint, GLbitfield); +#define glSampleMaski flextglSampleMaski +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage2DMultisample)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean); +#define glTexStorage2DMultisample flextglTexStorage2DMultisample +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStages)(GLuint, GLbitfield, GLuint); +#define glUseProgramStages flextglUseProgramStages +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipeline)(GLuint); +#define glValidateProgramPipeline flextglValidateProgramPipeline +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribBinding)(GLuint, GLuint); +#define glVertexAttribBinding flextglVertexAttribBinding +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribFormat)(GLuint, GLint, GLenum, GLboolean, GLuint); +#define glVertexAttribFormat flextglVertexAttribFormat +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexAttribIFormat)(GLuint, GLint, GLenum, GLuint); +#define glVertexAttribIFormat flextglVertexAttribIFormat +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglVertexBindingDivisor)(GLuint, GLuint); +#define glVertexBindingDivisor flextglVertexBindingDivisor + +/* GL_EXT_copy_image */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglCopyImageSubDataEXT)(GLuint, GLenum, GLint, GLint, GLint, GLint, GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei); +#define glCopyImageSubDataEXT flextglCopyImageSubDataEXT + +/* GL_EXT_debug_label */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelEXT)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetObjectLabelEXT flextglGetObjectLabelEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglLabelObjectEXT)(GLenum, GLuint, GLsizei, const GLchar *); +#define glLabelObjectEXT flextglLabelObjectEXT + +/* GL_EXT_debug_marker */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglInsertEventMarkerEXT)(GLsizei, const GLchar *); +#define glInsertEventMarkerEXT flextglInsertEventMarkerEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPopGroupMarkerEXT)(void); +#define glPopGroupMarkerEXT flextglPopGroupMarkerEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPushGroupMarkerEXT)(GLsizei, const GLchar *); +#define glPushGroupMarkerEXT flextglPushGroupMarkerEXT + +/* GL_EXT_disjoint_timer_query */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBeginQueryEXT)(GLenum, GLuint); +#define glBeginQueryEXT flextglBeginQueryEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteQueriesEXT)(GLsizei, const GLuint *); +#define glDeleteQueriesEXT flextglDeleteQueriesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEndQueryEXT)(GLenum); +#define glEndQueryEXT flextglEndQueryEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenQueriesEXT)(GLsizei, GLuint *); +#define glGenQueriesEXT flextglGenQueriesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjecti64vEXT)(GLuint, GLenum, GLint64 *); +#define glGetQueryObjecti64vEXT flextglGetQueryObjecti64vEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectivEXT)(GLuint, GLenum, GLint *); +#define glGetQueryObjectivEXT flextglGetQueryObjectivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectui64vEXT)(GLuint, GLenum, GLuint64 *); +#define glGetQueryObjectui64vEXT flextglGetQueryObjectui64vEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryObjectuivEXT)(GLuint, GLenum, GLuint *); +#define glGetQueryObjectuivEXT flextglGetQueryObjectuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetQueryivEXT)(GLenum, GLenum, GLint *); +#define glGetQueryivEXT flextglGetQueryivEXT +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsQueryEXT)(GLuint); +#define glIsQueryEXT flextglIsQueryEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglQueryCounterEXT)(GLuint, GLenum); +#define glQueryCounterEXT flextglQueryCounterEXT + +/* GL_EXT_draw_buffers_indexed */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationSeparateiEXT)(GLuint, GLenum, GLenum); +#define glBlendEquationSeparateiEXT flextglBlendEquationSeparateiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendEquationiEXT)(GLuint, GLenum); +#define glBlendEquationiEXT flextglBlendEquationiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendFuncSeparateiEXT)(GLuint, GLenum, GLenum, GLenum, GLenum); +#define glBlendFuncSeparateiEXT flextglBlendFuncSeparateiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendFunciEXT)(GLuint, GLenum, GLenum); +#define glBlendFunciEXT flextglBlendFunciEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglColorMaskiEXT)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +#define glColorMaskiEXT flextglColorMaskiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDisableiEXT)(GLenum, GLuint); +#define glDisableiEXT flextglDisableiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglEnableiEXT)(GLenum, GLuint); +#define glEnableiEXT flextglEnableiEXT +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsEnablediEXT)(GLenum, GLuint); +#define glIsEnablediEXT flextglIsEnablediEXT + +/* GL_EXT_geometry_shader */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTextureEXT)(GLenum, GLenum, GLuint, GLint); +#define glFramebufferTextureEXT flextglFramebufferTextureEXT + +/* GL_EXT_multi_draw_arrays */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawArraysEXT)(GLenum, const GLint *, const GLsizei *, GLsizei); +#define glMultiDrawArraysEXT flextglMultiDrawArraysEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglMultiDrawElementsEXT)(GLenum, const GLsizei *, GLenum, const void *const*, GLsizei); +#define glMultiDrawElementsEXT flextglMultiDrawElementsEXT + +/* GL_EXT_multisampled_render_to_texture */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglFramebufferTexture2DMultisampleEXT)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); +#define glFramebufferTexture2DMultisampleEXT flextglFramebufferTexture2DMultisampleEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); +#define glRenderbufferStorageMultisampleEXT flextglRenderbufferStorageMultisampleEXT + +/* GL_EXT_primitive_bounding_box */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPrimitiveBoundingBoxEXT)(GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +#define glPrimitiveBoundingBoxEXT flextglPrimitiveBoundingBoxEXT + +/* GL_EXT_robustness */ + +GLAPI FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusEXT)(void); +#define glGetGraphicsResetStatusEXT flextglGetGraphicsResetStatusEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvEXT)(GLuint, GLint, GLsizei, GLfloat *); +#define glGetnUniformfvEXT flextglGetnUniformfvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivEXT)(GLuint, GLint, GLsizei, GLint *); +#define glGetnUniformivEXT flextglGetnUniformivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsEXT)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *); +#define glReadnPixelsEXT flextglReadnPixelsEXT + +/* GL_EXT_separate_shader_objects */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglActiveShaderProgramEXT)(GLuint, GLuint); +#define glActiveShaderProgramEXT flextglActiveShaderProgramEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBindProgramPipelineEXT)(GLuint); +#define glBindProgramPipelineEXT flextglBindProgramPipelineEXT +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglCreateShaderProgramvEXT)(GLenum, GLsizei, const GLchar **); +#define glCreateShaderProgramvEXT flextglCreateShaderProgramvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDeleteProgramPipelinesEXT)(GLsizei, const GLuint *); +#define glDeleteProgramPipelinesEXT flextglDeleteProgramPipelinesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGenProgramPipelinesEXT)(GLsizei, GLuint *); +#define glGenProgramPipelinesEXT flextglGenProgramPipelinesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineInfoLogEXT)(GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetProgramPipelineInfoLogEXT flextglGetProgramPipelineInfoLogEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetProgramPipelineivEXT)(GLuint, GLenum, GLint *); +#define glGetProgramPipelineivEXT flextglGetProgramPipelineivEXT +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglIsProgramPipelineEXT)(GLuint); +#define glIsProgramPipelineEXT flextglIsProgramPipelineEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramParameteriEXT)(GLuint, GLenum, GLint); +#define glProgramParameteriEXT flextglProgramParameteriEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fEXT)(GLuint, GLint, GLfloat); +#define glProgramUniform1fEXT flextglProgramUniform1fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform1fvEXT flextglProgramUniform1fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1iEXT)(GLuint, GLint, GLint); +#define glProgramUniform1iEXT flextglProgramUniform1iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform1ivEXT flextglProgramUniform1ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uiEXT)(GLuint, GLint, GLuint); +#define glProgramUniform1uiEXT flextglProgramUniform1uiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform1uivEXT)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform1uivEXT flextglProgramUniform1uivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fEXT)(GLuint, GLint, GLfloat, GLfloat); +#define glProgramUniform2fEXT flextglProgramUniform2fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform2fvEXT flextglProgramUniform2fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2iEXT)(GLuint, GLint, GLint, GLint); +#define glProgramUniform2iEXT flextglProgramUniform2iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform2ivEXT flextglProgramUniform2ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uiEXT)(GLuint, GLint, GLuint, GLuint); +#define glProgramUniform2uiEXT flextglProgramUniform2uiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform2uivEXT)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform2uivEXT flextglProgramUniform2uivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat); +#define glProgramUniform3fEXT flextglProgramUniform3fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform3fvEXT flextglProgramUniform3fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3iEXT)(GLuint, GLint, GLint, GLint, GLint); +#define glProgramUniform3iEXT flextglProgramUniform3iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform3ivEXT flextglProgramUniform3ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint); +#define glProgramUniform3uiEXT flextglProgramUniform3uiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform3uivEXT)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform3uivEXT flextglProgramUniform3uivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fEXT)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat); +#define glProgramUniform4fEXT flextglProgramUniform4fEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4fvEXT)(GLuint, GLint, GLsizei, const GLfloat *); +#define glProgramUniform4fvEXT flextglProgramUniform4fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4iEXT)(GLuint, GLint, GLint, GLint, GLint, GLint); +#define glProgramUniform4iEXT flextglProgramUniform4iEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4ivEXT)(GLuint, GLint, GLsizei, const GLint *); +#define glProgramUniform4ivEXT flextglProgramUniform4ivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uiEXT)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint); +#define glProgramUniform4uiEXT flextglProgramUniform4uiEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniform4uivEXT)(GLuint, GLint, GLsizei, const GLuint *); +#define glProgramUniform4uivEXT flextglProgramUniform4uivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix2fvEXT flextglProgramUniformMatrix2fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix2x3fvEXT flextglProgramUniformMatrix2x3fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix2x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix2x4fvEXT flextglProgramUniformMatrix2x4fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix3fvEXT flextglProgramUniformMatrix3fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix3x2fvEXT flextglProgramUniformMatrix3x2fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix3x4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix3x4fvEXT flextglProgramUniformMatrix3x4fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix4fvEXT flextglProgramUniformMatrix4fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x2fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix4x2fvEXT flextglProgramUniformMatrix4x2fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglProgramUniformMatrix4x3fvEXT)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *); +#define glProgramUniformMatrix4x3fvEXT flextglProgramUniformMatrix4x3fvEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglUseProgramStagesEXT)(GLuint, GLbitfield, GLuint); +#define glUseProgramStagesEXT flextglUseProgramStagesEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglValidateProgramPipelineEXT)(GLuint); +#define glValidateProgramPipelineEXT flextglValidateProgramPipelineEXT + +/* GL_EXT_tessellation_shader */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPatchParameteriEXT)(GLenum, GLint); +#define glPatchParameteriEXT flextglPatchParameteriEXT + +/* GL_EXT_texture_border_clamp */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIivEXT)(GLuint, GLenum, GLint *); +#define glGetSamplerParameterIivEXT flextglGetSamplerParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetSamplerParameterIuivEXT)(GLuint, GLenum, GLuint *); +#define glGetSamplerParameterIuivEXT flextglGetSamplerParameterIuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIivEXT)(GLenum, GLenum, GLint *); +#define glGetTexParameterIivEXT flextglGetTexParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetTexParameterIuivEXT)(GLenum, GLenum, GLuint *); +#define glGetTexParameterIuivEXT flextglGetTexParameterIuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIivEXT)(GLuint, GLenum, const GLint *); +#define glSamplerParameterIivEXT flextglSamplerParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglSamplerParameterIuivEXT)(GLuint, GLenum, const GLuint *); +#define glSamplerParameterIuivEXT flextglSamplerParameterIuivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIivEXT)(GLenum, GLenum, const GLint *); +#define glTexParameterIivEXT flextglTexParameterIivEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexParameterIuivEXT)(GLenum, GLenum, const GLuint *); +#define glTexParameterIuivEXT flextglTexParameterIuivEXT + +/* GL_EXT_texture_buffer */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexBufferEXT)(GLenum, GLenum, GLuint); +#define glTexBufferEXT flextglTexBufferEXT +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexBufferRangeEXT)(GLenum, GLenum, GLuint, GLintptr, GLsizeiptr); +#define glTexBufferRangeEXT flextglTexBufferRangeEXT + +/* GL_KHR_blend_equation_advanced */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglBlendBarrierKHR)(void); +#define glBlendBarrierKHR flextglBlendBarrierKHR + +/* GL_KHR_debug */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageCallbackKHR)(GLDEBUGPROCKHR, const void *); +#define glDebugMessageCallbackKHR flextglDebugMessageCallbackKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageControlKHR)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean); +#define glDebugMessageControlKHR flextglDebugMessageControlKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglDebugMessageInsertKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *); +#define glDebugMessageInsertKHR flextglDebugMessageInsertKHR +GLAPI FLEXTGL_EXPORT GLuint(APIENTRY *flextglGetDebugMessageLogKHR)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *); +#define glGetDebugMessageLogKHR flextglGetDebugMessageLogKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectLabelKHR)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *); +#define glGetObjectLabelKHR flextglGetObjectLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetObjectPtrLabelKHR)(const void *, GLsizei, GLsizei *, GLchar *); +#define glGetObjectPtrLabelKHR flextglGetObjectPtrLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetPointervKHR)(GLenum, void **); +#define glGetPointervKHR flextglGetPointervKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglObjectLabelKHR)(GLenum, GLuint, GLsizei, const GLchar *); +#define glObjectLabelKHR flextglObjectLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglObjectPtrLabelKHR)(const void *, GLsizei, const GLchar *); +#define glObjectPtrLabelKHR flextglObjectPtrLabelKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPopDebugGroupKHR)(void); +#define glPopDebugGroupKHR flextglPopDebugGroupKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPushDebugGroupKHR)(GLenum, GLuint, GLsizei, const GLchar *); +#define glPushDebugGroupKHR flextglPushDebugGroupKHR + +/* GL_KHR_robustness */ + +GLAPI FLEXTGL_EXPORT GLenum(APIENTRY *flextglGetGraphicsResetStatusKHR)(void); +#define glGetGraphicsResetStatusKHR flextglGetGraphicsResetStatusKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformfvKHR)(GLuint, GLint, GLsizei, GLfloat *); +#define glGetnUniformfvKHR flextglGetnUniformfvKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformivKHR)(GLuint, GLint, GLsizei, GLint *); +#define glGetnUniformivKHR flextglGetnUniformivKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetnUniformuivKHR)(GLuint, GLint, GLsizei, GLuint *); +#define glGetnUniformuivKHR flextglGetnUniformuivKHR +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglReadnPixelsKHR)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *); +#define glReadnPixelsKHR flextglReadnPixelsKHR + +/* GL_NV_polygon_mode */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglPolygonModeNV)(GLenum, GLenum); +#define glPolygonModeNV flextglPolygonModeNV + +/* GL_OES_mapbuffer */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglGetBufferPointervOES)(GLenum, GLenum, void **); +#define glGetBufferPointervOES flextglGetBufferPointervOES +GLAPI FLEXTGL_EXPORT void *(APIENTRY *flextglMapBufferOES)(GLenum, GLenum); +#define glMapBufferOES flextglMapBufferOES +GLAPI FLEXTGL_EXPORT GLboolean(APIENTRY *flextglUnmapBufferOES)(GLenum); +#define glUnmapBufferOES flextglUnmapBufferOES + +/* GL_OES_sample_shading */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglMinSampleShadingOES)(GLfloat); +#define glMinSampleShadingOES flextglMinSampleShadingOES + +/* GL_OES_texture_storage_multisample_2d_array */ + +GLAPI FLEXTGL_EXPORT void(APIENTRY *flextglTexStorage3DMultisampleOES)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean); +#define glTexStorage3DMultisampleOES flextglTexStorage3DMultisampleOES + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.h.template b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.h.template new file mode 100644 index 000000000..eb9961c93 --- /dev/null +++ b/src/MagnumExternal/OpenGL/GLES3/flextGLWindowsDesktop.h.template @@ -0,0 +1,94 @@ +@require(passthru, functions, enums, options, version, extensions) +#ifndef _flextgl_h_ +#define _flextgl_h_ + +#include + +#include "Magnum/configure.h" + +/* Defensive include guards */ + +#if defined(__gl_h_) || defined(__gl2_h_) || defined(__gl3_h_) || defined(__gl31_h_) +#error Attempt to include auto-generated header after including gl3.h +#endif +#if defined(__gl2ext_h_) || defined(__gl3ext_h_) +#error Attempt to include auto-generated header after including gl3ext.h +#endif +#if defined(__gl2platform_h_) || defined(__gl3platform_h_) +#error Attempt to include auto-generated header after including gl3platform.h +#endif + +#define __gl_h_ +#define __gl2_h_ +#define __gl3_h_ +#define __gl31_h_ +#define __gl2ext_h_ +#define __gl3ext_h_ +#define __gl2platform_h_ +#define __gl3platform_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +void flextGLInit(); + +/* Function declaration macros */ + +#ifndef MAGNUM_BUILD_STATIC + #ifdef FlextGL_EXPORTS + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define FLEXTGL_EXPORT CORRADE_VISIBILITY_STATIC +#endif + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define APIENTRY WINAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/* Data types */ + +@passthru + +/* Enums */ + +@enums + +/* Function prototypes */ +@for cat,funcs in functions: +@if funcs: + +/* GL_@cat */ + + @for f in funcs: + @if f.name in ['BlendFunc', 'Clear', 'ClearColor', 'ClearDepth', 'ClearStencil', 'ColorMask', 'CullFace', 'DepthFunc', 'DepthMask', 'DepthRange', 'Disable', 'DrawBuffer', 'Enable', 'Finish', 'Flush', 'FrontFace', 'GetBooleanv', 'GetDoublev', 'GetError', 'GetFloatv', 'GetIntegerv', 'GetString', 'GetTexImage', 'GetTexLevelParameterfv', 'GetTexLevelParameteriv', 'GetTexParameterfv', 'GetTexParameteriv', 'Hint', 'IsEnabled', 'LineWidth', 'LogicOp', 'PixelStoref', 'PixelStorei', 'PointSize', 'PolygonMode', 'ReadBuffer', 'ReadPixels', 'Scissor', 'StencilFunc', 'StencilMask', 'StencilOp', 'TexImage1D', 'TexImage2D', 'TexParameterf', 'TexParameterfv', 'TexParameteri', 'TexParameteriv', 'Viewport', 'BindTexture', 'CopyTexImage1D', 'CopyTexImage2D', 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'DeleteTextures', 'DrawArrays', 'DrawElements', 'GenTextures', 'IsTexture', 'PolygonOffset', 'TexSubImage1D', 'TexSubImage2D']: +GLAPI FLEXTGL_EXPORT @f.returntype APIENTRY gl@f.name\ +(@f.param_type_list_string()); + @else: +GLAPI FLEXTGL_EXPORT @f.returntype\ +(APIENTRY *flextgl@f.name)(@f.param_type_list_string()); +#define gl@f.name flextgl@f.name + @end + @end +@end +@end + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/MagnumPlugins/CMakeLists.txt b/src/MagnumPlugins/CMakeLists.txt index 13b85f2f9..75deddec1 100644 --- a/src/MagnumPlugins/CMakeLists.txt +++ b/src/MagnumPlugins/CMakeLists.txt @@ -24,11 +24,11 @@ # # Wrapper for creating given plugin type -macro(add_plugin plugin_name debug_install_dir release_install_dir metadata_file) +macro(add_plugin plugin_name debug_install_dirs release_install_dirs metadata_file) if(NOT BUILD_PLUGINS_STATIC) - corrade_add_plugin(${plugin_name} ${debug_install_dir} ${release_install_dir} ${metadata_file} ${ARGN}) + corrade_add_plugin(${plugin_name} "${debug_install_dirs}" "${release_install_dirs}" ${metadata_file} ${ARGN}) else() - corrade_add_static_plugin(${plugin_name} ${release_install_dir} ${metadata_file} ${ARGN}) + corrade_add_static_plugin(${plugin_name} "${release_install_dirs}" ${metadata_file} ${ARGN}) endif() endmacro() diff --git a/src/MagnumPlugins/MagnumFont/CMakeLists.txt b/src/MagnumPlugins/MagnumFont/CMakeLists.txt index a5cab2251..35ce546f7 100644 --- a/src/MagnumPlugins/MagnumFont/CMakeLists.txt +++ b/src/MagnumPlugins/MagnumFont/CMakeLists.txt @@ -23,6 +23,13 @@ # DEALINGS IN THE SOFTWARE. # +if(BUILD_PLUGINS_STATIC) + set(MAGNUM_MAGNUMFONT_BUILD_STATIC 1) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + set(MagnumFont_SRCS MagnumFont.cpp) @@ -34,12 +41,17 @@ add_library(MagnumFontObjects OBJECT ${MagnumFont_SRCS} ${MagnumFont_HEADERS}) target_include_directories(MagnumFontObjects PUBLIC $) +if(NOT BUILD_PLUGINS_STATIC) + target_compile_definitions(MagnumFontObjects PRIVATE "MagnumFontObjects_EXPORTS") +endif() if(NOT BUILD_PLUGINS_STATIC OR BUILD_STATIC_PIC) set_target_properties(MagnumFontObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) endif() # MagnumFont plugin -add_plugin(MagnumFont ${MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR} +add_plugin(MagnumFont + "${MAGNUM_PLUGINS_FONT_DEBUG_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_FONT_DEBUG_LIBRARY_INSTALL_DIR}" + "${MAGNUM_PLUGINS_FONT_RELEASE_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_FONT_RELEASE_LIBRARY_INSTALL_DIR}" MagnumFont.conf $ pluginRegistration.cpp) @@ -53,6 +65,7 @@ if(CORRADE_TARGET_WINDOWS) endif() install(FILES ${MagnumFont_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/MagnumFont) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/configure.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/MagnumFont) if(BUILD_GL_TESTS) # On Win32 we need to avoid dllimporting TgaImporter symbols, because it @@ -63,9 +76,13 @@ if(BUILD_GL_TESTS) add_library(MagnumMagnumFontTestLib STATIC ${MagnumFont_SRCS} ${MagnumFont_HEADERS}) - target_compile_definitions(MagnumMagnumFontTestLib PRIVATE "MAGNUM_TGAIMPORTER_BUILD_STATIC") + target_compile_definitions(MagnumMagnumFontTestLib + PRIVATE "MAGNUM_TGAIMPORTER_BUILD_STATIC" + PUBLIC "MAGNUM_MAGNUMFONT_BUILD_STATIC") else() - add_library(MagnumMagnumFontTestLib STATIC $) + add_library(MagnumMagnumFontTestLib STATIC + $ + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details endif() target_link_libraries(MagnumMagnumFontTestLib Magnum MagnumText MagnumTgaImporterTestLib) diff --git a/src/MagnumPlugins/MagnumFont/MagnumFont.h b/src/MagnumPlugins/MagnumFont/MagnumFont.h index 0496e64a3..5f12a7ca3 100644 --- a/src/MagnumPlugins/MagnumFont/MagnumFont.h +++ b/src/MagnumPlugins/MagnumFont/MagnumFont.h @@ -32,6 +32,21 @@ #include "Magnum/Text/AbstractFont.h" #include "Magnum/Trade/Trade.h" +#include "MagnumPlugins/MagnumFont/configure.h" + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_MAGNUMFONT_BUILD_STATIC + #if defined(MagnumFont_EXPORTS) || defined(MagnumFontObjects_EXPORTS) + #define MAGNUM_MAGNUMFONT_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define MAGNUM_MAGNUMFONT_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define MAGNUM_MAGNUMFONT_EXPORT CORRADE_VISIBILITY_STATIC +#endif +#define MAGNUM_MAGNUMFONT_LOCAL CORRADE_VISIBILITY_LOCAL +#endif + namespace Magnum { namespace Text { /** @@ -101,9 +116,9 @@ The file syntax is as in following: # ... -@see Trade::TgaImporter +@see @ref Trade::TgaImporter */ -class MagnumFont: public AbstractFont { +class MAGNUM_MAGNUMFONT_EXPORT MagnumFont: public AbstractFont { public: /** @brief Default constructor */ explicit MagnumFont(); @@ -116,25 +131,18 @@ class MagnumFont: public AbstractFont { private: struct Data; - Features doFeatures() const override; - - bool doIsOpened() const override; - - Metrics doOpenData(const std::vector>>& data, Float) override; - - Metrics doOpenFile(const std::string& filename, Float) override; - - void doClose() override; - - UnsignedInt doGlyphId(char32_t character) override; - - Vector2 doGlyphAdvance(UnsignedInt glyph) override; - - std::unique_ptr doCreateGlyphCache() override; + MAGNUM_MAGNUMFONT_LOCAL Features doFeatures() const override; + MAGNUM_MAGNUMFONT_LOCAL bool doIsOpened() const override; + MAGNUM_MAGNUMFONT_LOCAL Metrics doOpenData(const std::vector>>& data, Float) override; + MAGNUM_MAGNUMFONT_LOCAL Metrics doOpenFile(const std::string& filename, Float) override; + MAGNUM_MAGNUMFONT_LOCAL void doClose() override; - std::unique_ptr doLayout(const GlyphCache& cache, Float size, const std::string& text) override; + MAGNUM_MAGNUMFONT_LOCAL UnsignedInt doGlyphId(char32_t character) override; + MAGNUM_MAGNUMFONT_LOCAL Vector2 doGlyphAdvance(UnsignedInt glyph) override; + MAGNUM_MAGNUMFONT_LOCAL std::unique_ptr doCreateGlyphCache() override; + MAGNUM_MAGNUMFONT_LOCAL std::unique_ptr doLayout(const GlyphCache& cache, Float size, const std::string& text) override; - Metrics openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); + MAGNUM_MAGNUMFONT_LOCAL Metrics openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); Data* _opened; }; diff --git a/src/MagnumPlugins/TgaImageConverter/Test/configure.h.cmake b/src/MagnumPlugins/MagnumFont/configure.h.cmake similarity index 95% rename from src/MagnumPlugins/TgaImageConverter/Test/configure.h.cmake rename to src/MagnumPlugins/MagnumFont/configure.h.cmake index c2d991989..b3d53b96a 100644 --- a/src/MagnumPlugins/TgaImageConverter/Test/configure.h.cmake +++ b/src/MagnumPlugins/MagnumFont/configure.h.cmake @@ -23,4 +23,4 @@ DEALINGS IN THE SOFTWARE. */ -#define TGAIMAGECONVERTER_TEST_DIR "${CMAKE_CURRENT_BINARY_DIR}" +#cmakedefine MAGNUM_MAGNUMFONT_BUILD_STATIC diff --git a/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt b/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt index 7f2a5661b..86a0a98a8 100644 --- a/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt +++ b/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt @@ -23,6 +23,13 @@ # DEALINGS IN THE SOFTWARE. # +if(BUILD_PLUGINS_STATIC) + set(MAGNUM_MAGNUMFONTCONVERTER_BUILD_STATIC 1) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + set(MagnumFontConverter_SRCS MagnumFontConverter.cpp) @@ -34,12 +41,17 @@ add_library(MagnumFontConverterObjects OBJECT ${MagnumFontConverter_SRCS} ${MagnumFontConverter_HEADERS}) target_include_directories(MagnumFontConverterObjects PUBLIC $) +if(NOT BUILD_PLUGINS_STATIC) + target_compile_definitions(MagnumFontConverterObjects PRIVATE "MagnumFontConverterObjects_EXPORTS") +endif() if(NOT BUILD_PLUGINS_STATIC OR BUILD_STATIC_PIC) set_target_properties(MagnumFontConverterObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) endif() # MagnumFontConverter plugin -add_plugin(MagnumFontConverter ${MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_INSTALL_DIR} +add_plugin(MagnumFontConverter + "${MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_LIBRARY_INSTALL_DIR}" + "${MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_LIBRARY_INSTALL_DIR}" MagnumFontConverter.conf $ pluginRegistration.cpp) @@ -53,6 +65,7 @@ if(CORRADE_TARGET_WINDOWS) endif() install(FILES ${MagnumFontConverter_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/MagnumFontConverter) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/configure.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/MagnumFontConverter) if(BUILD_GL_TESTS) # On Win32 we need to avoid dllimporting TgaImageConverter symbols, because @@ -63,9 +76,13 @@ if(BUILD_GL_TESTS) add_library(MagnumMagnumFontConverterTestLib STATIC ${MagnumFontConverter_SRCS} ${MagnumFontConverter_HEADERS}) - target_compile_definitions(MagnumMagnumFontConverterTestLib PRIVATE "MAGNUM_TGAIMAGECONVERTER_BUILD_STATIC") + target_compile_definitions(MagnumMagnumFontConverterTestLib + PRIVATE "MAGNUM_TGAIMAGECONVERTER_BUILD_STATIC" + PUBLIC "MAGNUM_MAGNUMFONTCONVERTER_BUILD_STATIC") else() - add_library(MagnumMagnumFontConverterTestLib STATIC $) + add_library(MagnumMagnumFontConverterTestLib STATIC + $ + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details endif() target_link_libraries(MagnumMagnumFontConverterTestLib Magnum MagnumText MagnumTgaImageConverterTestLib) diff --git a/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.h b/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.h index 4f6595db2..8c72749c0 100644 --- a/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.h +++ b/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.h @@ -31,6 +31,21 @@ #include "Magnum/Text/AbstractFontConverter.h" +#include "MagnumPlugins/MagnumFontConverter/configure.h" + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_MAGNUMFONTCONVERTER_BUILD_STATIC + #if defined(MagnumFontConverter_EXPORTS) || defined(MagnumFontConverterObjects_EXPORTS) + #define MAGNUM_MAGNUMFONTCONVERTER_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define MAGNUM_MAGNUMFONTCONVERTER_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define MAGNUM_MAGNUMFONTCONVERTER_EXPORT CORRADE_VISIBILITY_STATIC +#endif +#define MAGNUM_MAGNUMFONTCONVERTER_LOCAL CORRADE_VISIBILITY_LOCAL +#endif + namespace Magnum { namespace Text { /** @@ -49,7 +64,7 @@ dependency of another plugin, you need to request `MagnumFontConverter` component of `Magnum` package in CMake and link to `Magnum::MagnumFontConverter` target. See @ref building, @ref cmake and @ref plugins for more information. */ -class MagnumFontConverter: public Text::AbstractFontConverter { +class MAGNUM_MAGNUMFONTCONVERTER_EXPORT MagnumFontConverter: public Text::AbstractFontConverter { public: /** @brief Default constructor */ explicit MagnumFontConverter(); @@ -58,8 +73,8 @@ class MagnumFontConverter: public Text::AbstractFontConverter { explicit MagnumFontConverter(PluginManager::AbstractManager& manager, std::string plugin); private: - Features doFeatures() const override; - std::vector>> doExportFontToData(AbstractFont& font, GlyphCache& cache, const std::string& filename, const std::u32string& characters) const override; + MAGNUM_MAGNUMFONTCONVERTER_LOCAL Features doFeatures() const override; + MAGNUM_MAGNUMFONTCONVERTER_LOCAL std::vector>> doExportFontToData(AbstractFont& font, GlyphCache& cache, const std::string& filename, const std::u32string& characters) const override; }; }} diff --git a/src/MagnumPlugins/MagnumFontConverter/Test/CMakeLists.txt b/src/MagnumPlugins/MagnumFontConverter/Test/CMakeLists.txt index 2e859b71b..fa42cba7a 100644 --- a/src/MagnumPlugins/MagnumFontConverter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/MagnumFontConverter/Test/CMakeLists.txt @@ -31,7 +31,6 @@ corrade_add_test(MagnumFontConverterGLTest MagnumFontConverterGLTest.cpp LIBRARI MagnumTgaImporterTestLib ${GL_TEST_LIBRARIES}) target_include_directories(MagnumFontConverterGLTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) - # On Win32 we need to avoid dllimporting TgaImporter symbols, because it would # search for the symbols in some DLL even though they were linked statically. # However it apparently doesn't matter that they were dllexported when building diff --git a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp index 6c34c61aa..c2fbcfad6 100644 --- a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp +++ b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp @@ -88,7 +88,7 @@ void MagnumFontConverterGLTest::exportFont() { case 2: return {23, 0}; } - CORRADE_ASSERT_UNREACHABLE(); + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } bool _opened; diff --git a/src/MagnumPlugins/MagnumFontConverter/configure.h.cmake b/src/MagnumPlugins/MagnumFontConverter/configure.h.cmake new file mode 100644 index 000000000..1eb6102a9 --- /dev/null +++ b/src/MagnumPlugins/MagnumFontConverter/configure.h.cmake @@ -0,0 +1,26 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#cmakedefine MAGNUM_MAGNUMFONTCONVERTER_BUILD_STATIC diff --git a/src/MagnumPlugins/ObjImporter/CMakeLists.txt b/src/MagnumPlugins/ObjImporter/CMakeLists.txt index 8973e22c2..7b3c1cdf7 100644 --- a/src/MagnumPlugins/ObjImporter/CMakeLists.txt +++ b/src/MagnumPlugins/ObjImporter/CMakeLists.txt @@ -23,6 +23,13 @@ # DEALINGS IN THE SOFTWARE. # +if(BUILD_PLUGINS_STATIC) + set(MAGNUM_OBJIMPORTER_BUILD_STATIC 1) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + set(ObjImporter_SRCS ObjImporter.cpp) @@ -34,12 +41,17 @@ add_library(ObjImporterObjects OBJECT ${ObjImporter_SRCS} ${ObjImporter_HEADERS}) target_include_directories(ObjImporterObjects PUBLIC $) +if(NOT BUILD_PLUGINS_STATIC) + target_compile_definitions(ObjImporterObjects PRIVATE "ObjImporterObjects_EXPORTS") +endif() if(NOT BUILD_PLUGINS_STATIC OR BUILD_STATIC_PIC) set_target_properties(ObjImporterObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) endif() # ObjImporter plugin -add_plugin(ObjImporter ${MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR} +add_plugin(ObjImporter + "${MAGNUM_PLUGINS_IMPORTER_DEBUG_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMPORTER_DEBUG_LIBRARY_INSTALL_DIR}" + "${MAGNUM_PLUGINS_IMPORTER_RELEASE_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMPORTER_RELEASE_LIBRARY_INSTALL_DIR}" ObjImporter.conf $ pluginRegistration.cpp) @@ -49,10 +61,14 @@ endif() target_link_libraries(ObjImporter Magnum MagnumMeshTools) install(FILES ${ObjImporter_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/ObjImporter) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/configure.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/ObjImporter) if(BUILD_TESTS) - add_library(MagnumObjImporterTestLib STATIC $) + add_library(MagnumObjImporterTestLib STATIC + $ + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details target_link_libraries(MagnumObjImporterTestLib Magnum MagnumMeshTools) + add_subdirectory(Test) endif() diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp index 125237f54..d2059cb16 100644 --- a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp @@ -38,10 +38,6 @@ #include "Magnum/Math/Vector3.h" #include "Magnum/Trade/MeshData3D.h" -#if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(CORRADE_TARGET_ANDROID) -#include -#endif - namespace Magnum { namespace Trade { struct ObjImporter::File { @@ -66,16 +62,16 @@ template Math::Vector extractFloatData(std::strin Math::Vector output; - #if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(CORRADE_TARGET_ANDROID) - std::istringstream in; - #endif - for(std::size_t i = 0; i != size; ++i) { - #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) + #ifndef CORRADE_TARGET_ANDROID output[i] = std::stof(data[i]); #else - in.str(data[i]); - in >> output[i]; + /* CRAPPY ANDROID GODDAMIT! It's also not exposed in std:: namespace, + unlike std::strtoul() and others. WTF! */ + char* end{}; + output[i] = strtof(data[i].data(), &end); + if(end == data[i].data() || output[i] == HUGE_VALF) + throw std::exception{}; #endif } @@ -84,11 +80,15 @@ template Math::Vector extractFloatData(std::strin Clang Analyzer happy */ CORRADE_INTERNAL_ASSERT(extra); - #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) + #ifndef CORRADE_TARGET_ANDROID *extra = std::stof(data.back()); #else - in.str(data.back()); - in >> *extra; + /* CRAPPY ANDROID GODDAMIT! It's also not exposed in std:: namespace, + unlike std::strtoul() and others. WTF! */ + char* end{}; + *extra = strtof(data.back().data(), &end); + if(end == data.back().data() || *extra == HUGE_VALF) + throw std::exception{}; #endif } @@ -361,7 +361,7 @@ std::optional ObjImporter::doMesh3D(UnsignedInt id) { primitive = MeshPrimitive::Triangles; - } else CORRADE_ASSERT_UNREACHABLE(); + } else CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ for(const std::string& indexTuple: indexTuples) { std::vector indices = Utility::String::split(indexTuple, '/'); @@ -370,35 +370,50 @@ std::optional ObjImporter::doMesh3D(UnsignedInt id) { return std::nullopt; } + #ifdef CORRADE_TARGET_ANDROID + char* end{}; + #endif + /* Position indices */ - #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) - positionIndices.push_back(std::stoul(indices[0]) - positionIndexOffset); - #else - std::istringstream in(indices[0]); - UnsignedInt index; - in >> index; - positionIndices.push_back(index - positionIndexOffset); + positionIndices.push_back( + #ifndef CORRADE_TARGET_ANDROID + std::stoul(indices[0]) + #else + std::strtoul(indices[0].data(), &end, 10) + #endif + - positionIndexOffset); + + #ifdef CORRADE_TARGET_ANDROID + if(end == indices[0].data()) throw std::exception{}; #endif /* Texture coordinates */ if(indices.size() == 2 || (indices.size() == 3 && !indices[1].empty())) { - #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) - textureCoordinateIndices.push_back(std::stoul(indices[1]) - textureCoordinateIndexOffset); - #else - in.str(indices[1]); - in >> index; - textureCoordinateIndices.push_back(index - textureCoordinateIndexOffset); + textureCoordinateIndices.push_back( + #ifndef CORRADE_TARGET_ANDROID + std::stoul(indices[1]) + #else + std::strtoul(indices[1].data(), &end, 10) + #endif + - textureCoordinateIndexOffset); + + #ifdef CORRADE_TARGET_ANDROID + if(end == indices[1].data()) throw std::exception{}; #endif } /* Normal indices */ if(indices.size() == 3) { - #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) - normalIndices.push_back(std::stoul(indices[2]) - normalIndexOffset); - #else - in.str(indices[2]); - in >> index; - normalIndices.push_back(index - normalIndexOffset); + normalIndices.push_back( + #ifndef CORRADE_TARGET_ANDROID + std::stoul(indices[2]) + #else + std::strtoul(indices[2].data(), &end, 10) + #endif + - normalIndexOffset); + + #ifdef CORRADE_TARGET_ANDROID + if(end == indices[2].data()) throw std::exception{}; #endif } } diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.h b/src/MagnumPlugins/ObjImporter/ObjImporter.h index 29d150f16..74e6d85dd 100644 --- a/src/MagnumPlugins/ObjImporter/ObjImporter.h +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.h @@ -31,6 +31,21 @@ #include "Magnum/Trade/AbstractImporter.h" +#include "MagnumPlugins/ObjImporter/configure.h" + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_OBJIMPORTER_BUILD_STATIC + #if defined(ObjImporter_EXPORTS) || defined(ObjImporterObjects_EXPORTS) + #define MAGNUM_OBJIMPORTER_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define MAGNUM_OBJIMPORTER_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define MAGNUM_OBJIMPORTER_EXPORT CORRADE_VISIBILITY_STATIC +#endif +#define MAGNUM_OBJIMPORTER_LOCAL CORRADE_VISIBILITY_LOCAL +#endif + namespace Magnum { namespace Trade { /** @@ -51,7 +66,7 @@ of another plugin, you need to request `ObjImporter` component of `Magnum` package in CMake and link to `Magnum::ObjImporter` target. See @ref building, @ref cmake and @ref plugins for more information. */ -class ObjImporter: public AbstractImporter { +class MAGNUM_OBJIMPORTER_EXPORT ObjImporter: public AbstractImporter { public: /** @brief Default constructor */ explicit ObjImporter(); @@ -64,19 +79,19 @@ class ObjImporter: public AbstractImporter { private: struct File; - Features doFeatures() const override; + MAGNUM_OBJIMPORTER_LOCAL Features doFeatures() const override; - bool doIsOpened() const override; - void doOpenData(Containers::ArrayView data) override; - void doOpenFile(const std::string& filename) override; - void doClose() override; + MAGNUM_OBJIMPORTER_LOCAL bool doIsOpened() const override; + MAGNUM_OBJIMPORTER_LOCAL void doOpenData(Containers::ArrayView data) override; + MAGNUM_OBJIMPORTER_LOCAL void doOpenFile(const std::string& filename) override; + MAGNUM_OBJIMPORTER_LOCAL void doClose() override; - UnsignedInt doMesh3DCount() const override; - Int doMesh3DForName(const std::string& name) override; - std::string doMesh3DName(UnsignedInt id) override; - std::optional doMesh3D(UnsignedInt id) override; + MAGNUM_OBJIMPORTER_LOCAL UnsignedInt doMesh3DCount() const override; + MAGNUM_OBJIMPORTER_LOCAL Int doMesh3DForName(const std::string& name) override; + MAGNUM_OBJIMPORTER_LOCAL std::string doMesh3DName(UnsignedInt id) override; + MAGNUM_OBJIMPORTER_LOCAL std::optional doMesh3D(UnsignedInt id) override; - void parseMeshNames(); + MAGNUM_OBJIMPORTER_LOCAL void parseMeshNames(); std::unique_ptr _file; }; diff --git a/src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt b/src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt index 134e83d4d..c6a15bcd5 100644 --- a/src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt @@ -23,8 +23,40 @@ # DEALINGS IN THE SOFTWARE. # +if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) + set(OBJIMPORTER_TEST_DIR ".") +else() + set(OBJIMPORTER_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure.h) -corrade_add_test(ObjImporterTest Test.cpp LIBRARIES MagnumObjImporterTestLib) +corrade_add_test(ObjImporterTest Test.cpp + LIBRARIES MagnumObjImporterTestLib + FILES + emptyFile.obj + keywords.obj + lineMesh.obj + missingData.obj + mixedPrimitives.obj + moreMeshes.obj + namedMesh.obj + normals.obj + optionalCoordinates.obj + pointMesh.obj + textureCoordinatesNormals.obj + textureCoordinates.obj + triangleMesh.obj + unnamedFirstMesh.obj + wrongIndexCount.obj + wrongNumberCount.obj + wrongNumbers.obj) target_include_directories(ObjImporterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +# On Win32 we need to avoid dllimporting ObjImporter symbols, because it would +# search for the symbols in some DLL even though they were linked statically. +# However it apparently doesn't matter that they were dllexported when building +# the static library. EH. +if(WIN32) + target_compile_definitions(ObjImporterTest PRIVATE "MAGNUM_OBJIMPORTER_BUILD_STATIC") +endif() diff --git a/src/MagnumPlugins/ObjImporter/Test/configure.h.cmake b/src/MagnumPlugins/ObjImporter/Test/configure.h.cmake index 459564c9c..04d28dd95 100644 --- a/src/MagnumPlugins/ObjImporter/Test/configure.h.cmake +++ b/src/MagnumPlugins/ObjImporter/Test/configure.h.cmake @@ -23,4 +23,4 @@ DEALINGS IN THE SOFTWARE. */ -#define OBJIMPORTER_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" +#define OBJIMPORTER_TEST_DIR "${OBJIMPORTER_TEST_DIR}" diff --git a/src/MagnumPlugins/ObjImporter/configure.h.cmake b/src/MagnumPlugins/ObjImporter/configure.h.cmake new file mode 100644 index 000000000..e30d44ad2 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/configure.h.cmake @@ -0,0 +1,26 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#cmakedefine MAGNUM_OBJIMPORTER_BUILD_STATIC diff --git a/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt b/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt index 2895f4618..6241bdeca 100644 --- a/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt +++ b/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt @@ -49,7 +49,9 @@ if(NOT BUILD_PLUGINS_STATIC OR BUILD_STATIC_PIC) endif() # TgaImageConverter plugin -add_plugin(TgaImageConverter ${MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_INSTALL_DIR} +add_plugin(TgaImageConverter + "${MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_LIBRARY_INSTALL_DIR}" + "${MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_LIBRARY_INSTALL_DIR}" TgaImageConverter.conf $ pluginRegistration.cpp) @@ -62,7 +64,9 @@ install(FILES ${TgaImageConverter_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/configure.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/TgaImageConverter) if(BUILD_TESTS) - add_library(MagnumTgaImageConverterTestLib STATIC $) + add_library(MagnumTgaImageConverterTestLib STATIC + $ + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details target_link_libraries(MagnumTgaImageConverterTestLib Magnum) add_subdirectory(Test) diff --git a/src/MagnumPlugins/TgaImageConverter/Test/CMakeLists.txt b/src/MagnumPlugins/TgaImageConverter/Test/CMakeLists.txt index aa1cb434a..ed5f15626 100644 --- a/src/MagnumPlugins/TgaImageConverter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/TgaImageConverter/Test/CMakeLists.txt @@ -23,11 +23,7 @@ # DEALINGS IN THE SOFTWARE. # -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/configure.h) - corrade_add_test(TgaImageConverterTest TgaImageConverterTest.cpp LIBRARIES MagnumTgaImageConverterTestLib MagnumTgaImporterTestLib) -target_include_directories(TgaImageConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # On Win32 we need to avoid dllimporting TgaImporter and TgaImageConverterTest # symbols, because it would search for the symbols in some DLL even though they # were linked statically. However it apparently doesn't matter that they were diff --git a/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp b/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp index 52b003d27..b05545083 100644 --- a/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp +++ b/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp @@ -36,8 +36,6 @@ #include "MagnumPlugins/TgaImageConverter/TgaImageConverter.h" #include "MagnumPlugins/TgaImporter/TgaImporter.h" -#include "configure.h" - namespace Magnum { namespace Trade { namespace Test { class TgaImageConverterTest: public TestSuite::Tester { @@ -87,18 +85,34 @@ TgaImageConverterTest::TgaImageConverterTest() { } void TgaImageConverterTest::wrongFormat() { - ImageView2D image(PixelFormat::RG, PixelType::UnsignedByte, {}, nullptr); + ImageView2D image{ + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + PixelFormat::RG, + #else + PixelFormat::LuminanceAlpha, + #endif + PixelType::UnsignedByte, {}, nullptr}; std::ostringstream out; Error redirectError{&out}; const auto data = TgaImageConverter().exportToData(image); CORRADE_VERIFY(!data); + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) CORRADE_COMPARE(out.str(), "Trade::TgaImageConverter::exportToData(): unsupported color format PixelFormat::RG\n"); + #else + CORRADE_COMPARE(out.str(), "Trade::TgaImageConverter::exportToData(): unsupported color format PixelFormat::LuminanceAlpha\n"); + #endif } void TgaImageConverterTest::wrongType() { - ImageView2D image(PixelFormat::Red, PixelType::Float, {}, nullptr); + ImageView2D image{ + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + PixelFormat::Red, + #else + PixelFormat::Luminance, + #endif + PixelType::Float, {}, nullptr}; std::ostringstream out; Error redirectError{&out}; diff --git a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp index af9817c0f..d4e37710c 100644 --- a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp +++ b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp @@ -91,14 +91,14 @@ Containers::Array TgaImageConverter::doExportToData(const ImageView2D& ima #endif header->imageType = 3; break; - default: CORRADE_ASSERT_UNREACHABLE(); + default: CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } header->bpp = pixelSize*8; header->width = UnsignedShort(Utility::Endianness::littleEndian(image.size().x())); header->height = UnsignedShort(Utility::Endianness::littleEndian(image.size().y())); /* Image data pointer including skip */ - const char* imageData = image.data() + std::get<0>(image.dataProperties()); + const char* imageData = image.data() + std::get<0>(image.dataProperties()).sum(); /* Fill data or copy them row by row if we need to drop the padding */ const std::size_t rowSize = image.size().x()*pixelSize; diff --git a/src/MagnumPlugins/TgaImporter/CMakeLists.txt b/src/MagnumPlugins/TgaImporter/CMakeLists.txt index b2ebfb43e..651a33a0c 100644 --- a/src/MagnumPlugins/TgaImporter/CMakeLists.txt +++ b/src/MagnumPlugins/TgaImporter/CMakeLists.txt @@ -50,7 +50,9 @@ if(NOT BUILD_PLUGINS_STATIC OR BUILD_STATIC_PIC) endif() # TgaImporter plugin -add_plugin(TgaImporter ${MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR} +add_plugin(TgaImporter + "${MAGNUM_PLUGINS_IMPORTER_DEBUG_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMPORTER_DEBUG_LIBRARY_INSTALL_DIR}" + "${MAGNUM_PLUGINS_IMPORTER_RELEASE_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMPORTER_RELEASE_LIBRARY_INSTALL_DIR}" TgaImporter.conf $ pluginRegistration.cpp) @@ -63,7 +65,9 @@ install(FILES ${TgaImporter_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTAL install(FILES ${CMAKE_CURRENT_BINARY_DIR}/configure.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/TgaImporter) if(BUILD_TESTS) - add_library(MagnumTgaImporterTestLib STATIC $) + add_library(MagnumTgaImporterTestLib STATIC + $ + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details target_link_libraries(MagnumTgaImporterTestLib Magnum) add_subdirectory(Test) diff --git a/src/MagnumPlugins/TgaImporter/Test/CMakeLists.txt b/src/MagnumPlugins/TgaImporter/Test/CMakeLists.txt index e3499dd25..ec9ad8ab6 100644 --- a/src/MagnumPlugins/TgaImporter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/TgaImporter/Test/CMakeLists.txt @@ -23,10 +23,18 @@ # DEALINGS IN THE SOFTWARE. # +if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) + set(TGAIMPORTER_TEST_DIR ".") +else() + set(TGAIMPORTER_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure.h) -corrade_add_test(TgaImporterTest TgaImporterTest.cpp LIBRARIES MagnumTgaImporterTestLib) +corrade_add_test(TgaImporterTest TgaImporterTest.cpp + LIBRARIES MagnumTgaImporterTestLib + FILES file.tga) target_include_directories(TgaImporterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # On Win32 we need to avoid dllimporting TgaImporter symbols, because it would # search for the symbols in some DLL even though they were linked statically. diff --git a/src/MagnumPlugins/TgaImporter/Test/configure.h.cmake b/src/MagnumPlugins/TgaImporter/Test/configure.h.cmake index cb625138d..9b4aac529 100644 --- a/src/MagnumPlugins/TgaImporter/Test/configure.h.cmake +++ b/src/MagnumPlugins/TgaImporter/Test/configure.h.cmake @@ -23,4 +23,4 @@ DEALINGS IN THE SOFTWARE. */ -#define TGAIMPORTER_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" +#define TGAIMPORTER_TEST_DIR "${TGAIMPORTER_TEST_DIR}" diff --git a/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt b/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt index adb4a558d..a3a13fe9f 100644 --- a/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt +++ b/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt @@ -23,7 +23,15 @@ # DEALINGS IN THE SOFTWARE. # +if(BUILD_PLUGINS_STATIC) + set(MAGNUM_WAVAUDIOIMPORTER_BUILD_STATIC 1) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + set(WavAudioImporter_SRCS + WavHeader.cpp WavImporter.cpp) set(WavAudioImporter_HEADERS @@ -37,12 +45,17 @@ add_library(WavAudioImporterObjects OBJECT target_include_directories(WavAudioImporterObjects PUBLIC $ $) +if(NOT BUILD_PLUGINS_STATIC) + target_compile_definitions(WavAudioImporterObjects PRIVATE "WavAudioImporterObjects_EXPORTS") +endif() if(NOT BUILD_PLUGINS_STATIC OR BUILD_STATIC_PIC) set_target_properties(WavAudioImporterObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) endif() # WavAudioImporter plugin -add_plugin(WavAudioImporter ${MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_INSTALL_DIR} +add_plugin(WavAudioImporter + "${MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_LIBRARY_INSTALL_DIR}" + "${MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_LIBRARY_INSTALL_DIR}" WavAudioImporter.conf $ pluginRegistration.cpp) @@ -52,10 +65,14 @@ endif() target_link_libraries(WavAudioImporter Magnum MagnumAudio) install(FILES ${WavAudioImporter_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/WavAudioImporter) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/configure.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/WavAudioImporter) if(BUILD_TESTS) - add_library(MagnumWavAudioImporterTestLib STATIC $) + add_library(MagnumWavAudioImporterTestLib STATIC + $ + ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details target_link_libraries(MagnumWavAudioImporterTestLib Magnum MagnumAudio) + add_subdirectory(Test) endif() diff --git a/src/MagnumPlugins/WavAudioImporter/Test/CMakeLists.txt b/src/MagnumPlugins/WavAudioImporter/Test/CMakeLists.txt index ec775d9e4..b76fab76c 100644 --- a/src/MagnumPlugins/WavAudioImporter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/WavAudioImporter/Test/CMakeLists.txt @@ -23,8 +23,55 @@ # DEALINGS IN THE SOFTWARE. # +if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) + set(WAVAUDIOIMPORTER_TEST_DIR ".") +else() + set(WAVAUDIOIMPORTER_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure.h) -corrade_add_test(WavAudioImporterTest WavImporterTest.cpp LIBRARIES MagnumWavAudioImporterTestLib) +corrade_add_test(WavAudioImporterTest WavImporterTest.cpp + LIBRARIES MagnumWavAudioImporterTestLib + FILES + unsupportedChannelCount.wav + unsupportedFormat.wav + wrongSignature.wav + + invalidPadding.wav + invalidLength.wav + invalidDataChunk.wav + invalidFactChunk.wav + + mono4.wav + mono8.wav + mono8junk.wav + mono8ALaw.wav + mono8MuLaw.wav + mono16.wav + mono24.wav + + stereo4.wav + stereo8.wav + stereo8ALaw.wav + stereo8MuLaw.wav + stereo12.wav + stereo16.wav + stereo24.wav + stereo32.wav + + mono32f.wav + stereo32f.wav + stereo64f.wav + + surround51Channel16.wav + surround71Channel24.wav) target_include_directories(WavAudioImporterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +# On Win32 we need to avoid dllimporting WavAudioImporter symbols, because it +# would search for the symbols in some DLL even though they were linked +# statically. However it apparently doesn't matter that they were dllexported +# when building the static library. EH. +if(WIN32) + target_compile_definitions(WavAudioImporterTest PRIVATE "MAGNUM_WAVAUDIOIMPORTER_BUILD_STATIC") +endif() diff --git a/src/MagnumPlugins/WavAudioImporter/Test/WavImporterTest.cpp b/src/MagnumPlugins/WavAudioImporter/Test/WavImporterTest.cpp index 3896c67e2..2c537ea57 100644 --- a/src/MagnumPlugins/WavAudioImporter/Test/WavImporterTest.cpp +++ b/src/MagnumPlugins/WavAudioImporter/Test/WavImporterTest.cpp @@ -3,6 +3,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 Vladimír Vondruš + Copyright © 2016 Alice Margatroid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -30,6 +31,7 @@ #include #include "MagnumPlugins/WavAudioImporter/WavImporter.h" +#include "MagnumPlugins/WavAudioImporter/WavHeader.h" #include "configure.h" @@ -43,8 +45,36 @@ class WavImporterTest: public TestSuite::Tester { void wrongSignature(); void unsupportedFormat(); void unsupportedChannelCount(); + + void invalidPadding(); + void invalidLength(); + void invalidDataChunk(); + void invalidFactChunk(); + + void mono4(); + void mono8(); + void mono8junk(); + void mono8ALaw(); + void mono8MuLaw(); void mono16(); + + void stereo4(); void stereo8(); + void stereo8ALaw(); + void stereo8MuLaw(); + void stereo12(); + void stereo16(); + void stereo24(); + void stereo32(); + + void mono32f(); + void stereo32f(); + void stereo64f(); + + void surround51Channel16(); + void surround71Channel24(); + + void debugAudioFormat(); }; WavImporterTest::WavImporterTest() { @@ -52,8 +82,36 @@ WavImporterTest::WavImporterTest() { &WavImporterTest::wrongSignature, &WavImporterTest::unsupportedFormat, &WavImporterTest::unsupportedChannelCount, + + &WavImporterTest::invalidPadding, + &WavImporterTest::invalidLength, + &WavImporterTest::invalidDataChunk, + &WavImporterTest::invalidFactChunk, + + &WavImporterTest::mono4, + &WavImporterTest::mono8, + &WavImporterTest::mono8junk, + &WavImporterTest::mono8ALaw, + &WavImporterTest::mono8MuLaw, &WavImporterTest::mono16, - &WavImporterTest::stereo8}); + + &WavImporterTest::stereo4, + &WavImporterTest::stereo8, + &WavImporterTest::stereo8ALaw, + &WavImporterTest::stereo8MuLaw, + &WavImporterTest::stereo12, + &WavImporterTest::stereo16, + &WavImporterTest::stereo24, + &WavImporterTest::stereo32, + + &WavImporterTest::mono32f, + &WavImporterTest::stereo32f, + &WavImporterTest::stereo64f, + + &WavImporterTest::surround51Channel16, + &WavImporterTest::surround71Channel24, + + &WavImporterTest::debugAudioFormat}); } void WavImporterTest::wrongSize() { @@ -80,7 +138,7 @@ void WavImporterTest::unsupportedFormat() { WavImporter importer; CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "unsupportedFormat.wav"))); - CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): unsupported audio format 2\n"); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): unsupported format Audio::WavAudioFormat::AdPcm\n"); } void WavImporterTest::unsupportedChannelCount() { @@ -89,7 +147,103 @@ void WavImporterTest::unsupportedChannelCount() { WavImporter importer; CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "unsupportedChannelCount.wav"))); - CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): unsupported channel count 6 with 8 bits per sample\n"); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): PCM with unsupported channel count 6 with 8 bits per sample\n"); +} + +void WavImporterTest::invalidPadding() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "invalidPadding.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): the file has improper size, expected 66 but got 73\n"); +} + +void WavImporterTest::invalidLength() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "invalidLength.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): the file has improper size, expected 160844 but got 80444\n"); +} + +void WavImporterTest::invalidDataChunk() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "invalidDataChunk.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): the file contains no data chunk\n"); +} + +void WavImporterTest::invalidFactChunk() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "invalidFactChunk.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::Mono16); + CORRADE_COMPARE(importer.frequency(), 22050); + + CORRADE_COMPARE_AS(importer.data().prefix(8), + Containers::Array::from(-27, -11, -1, -9, 24, -6, 127, -5).prefix(8), + TestSuite::Compare::Container); +} + +void WavImporterTest::mono4() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "mono4.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): unsupported format Audio::WavAudioFormat::AdPcm\n"); +} + +void WavImporterTest::mono8() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "mono8.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::Mono8); + CORRADE_COMPARE(importer.frequency(), 22050); + + CORRADE_COMPARE_AS(importer.data().prefix(4), + Containers::Array::from(127, 127, 127, 127).prefix(4), + TestSuite::Compare::Container); +} + +void WavImporterTest::mono8junk() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "mono8junk.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::Mono8); + CORRADE_COMPARE(importer.frequency(), 22050); + + CORRADE_COMPARE_AS(importer.data().prefix(4), + Containers::Array::from(127, 127, 127, 127).prefix(4), + TestSuite::Compare::Container); +} + +void WavImporterTest::mono8ALaw() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "mono8ALaw.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::MonoALaw); + CORRADE_COMPARE(importer.frequency(), 8000); + + CORRADE_COMPARE_AS(importer.data().prefix(8), + Containers::Array::from(87, 84, 85, 85, 85, -43, -43, -43).prefix(8), + TestSuite::Compare::Container); +} + +void WavImporterTest::mono8MuLaw() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "mono8MuLaw.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::MonoMuLaw); + CORRADE_COMPARE(importer.frequency(), 8000); + + CORRADE_COMPARE_AS(importer.data().prefix(8), + Containers::Array::from(-5, -3, -1, -2, -1, 127, 127, 126).prefix(8), + TestSuite::Compare::Container); } void WavImporterTest::mono16() { @@ -98,22 +252,169 @@ void WavImporterTest::mono16() { CORRADE_COMPARE(importer.format(), Buffer::Format::Mono16); CORRADE_COMPARE(importer.frequency(), 44000); + CORRADE_COMPARE_AS(importer.data(), Containers::Array::from('\x1d', '\x10', '\x71', '\xc5'), TestSuite::Compare::Container); } +void WavImporterTest::stereo4() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo4.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): unsupported format Audio::WavAudioFormat::AdPcm\n"); +} + void WavImporterTest::stereo8() { WavImporter importer; CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo8.wav"))); CORRADE_COMPARE(importer.format(), Buffer::Format::Stereo8); CORRADE_COMPARE(importer.frequency(), 96000); + CORRADE_COMPARE_AS(importer.data(), Containers::Array::from('\xde', '\xfe', '\xca', '\x7e'), TestSuite::Compare::Container); } +void WavImporterTest::stereo8ALaw() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo8ALaw.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::StereoALaw); + CORRADE_COMPARE(importer.frequency(), 8000); + + CORRADE_COMPARE_AS(importer.data().prefix(8), + Containers::Array::from(-43, -43, -43, -43, -43, -43, 85, -43).prefix(8), + TestSuite::Compare::Container); +} + +void WavImporterTest::stereo8MuLaw() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo8MuLaw.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::StereoMuLaw); + CORRADE_COMPARE(importer.frequency(), 8000); + + CORRADE_COMPARE_AS(importer.data().prefix(8), + Containers::Array::from(-1, -1, -1, -1, -1, -1, 127, -1).prefix(8), + TestSuite::Compare::Container); +} + +void WavImporterTest::stereo12() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo12.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): PCM with unsupported channel count 2 with 12 bits per sample\n"); +} + +void WavImporterTest::stereo16() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo16.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::Stereo16); + CORRADE_COMPARE(importer.frequency(), 44100); + + CORRADE_COMPARE_AS(importer.data(), + Containers::Array::from(39, 79, 39, 79), + TestSuite::Compare::Container); +} + +void WavImporterTest::stereo24() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo24.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): PCM with unsupported channel count 2 with 24 bits per sample\n"); +} + +void WavImporterTest::stereo32() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo32.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): PCM with unsupported channel count 2 with 32 bits per sample\n"); +} + +void WavImporterTest::mono32f() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "mono32f.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::MonoFloat); + CORRADE_COMPARE(importer.frequency(), 48000); + + CORRADE_COMPARE_AS(importer.data().prefix(16), + Containers::Array::from(0, 0, 0, 0, 108, 57, -103, 59, 3, 63, 42, 60, -33, -81, -120, 60).prefix(16), + TestSuite::Compare::Container); +} + +void WavImporterTest::stereo32f() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo32f.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::StereoFloat); + CORRADE_COMPARE(importer.frequency(), 44100); + + CORRADE_COMPARE_AS(importer.data().prefix(8), + Containers::Array::from(17, -77, -103, 56, 5, 50, 72, 56).prefix(8), + TestSuite::Compare::Container); +} + +void WavImporterTest::stereo64f() { + WavImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "stereo64f.wav"))); + + CORRADE_COMPARE(importer.format(), Buffer::Format::StereoDouble); + CORRADE_COMPARE(importer.frequency(), 8000); + + CORRADE_COMPARE_AS(importer.data().prefix(64), + Containers::Array::from(0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 16, 63, + 0, 0, 0, 0, 0, 0, 24, -65, + 0, 0, 0, 0, 0, 0, 0, 0).prefix(64), + TestSuite::Compare::Container); +} + +void WavImporterTest::surround51Channel16() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "surround51Channel16.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): unsupported format Audio::WavAudioFormat::Extensible\n"); +} + +void WavImporterTest::surround71Channel24() { + std::ostringstream out; + Error redirectError{&out}; + + WavImporter importer; + + CORRADE_VERIFY(!importer.openFile(Utility::Directory::join(WAVAUDIOIMPORTER_TEST_DIR, "surround71Channel24.wav"))); + CORRADE_COMPARE(out.str(), "Audio::WavImporter::openData(): unsupported format Audio::WavAudioFormat::Extensible\n"); +} + +void WavImporterTest::debugAudioFormat() { + std::ostringstream out; + + Debug{&out} << WavAudioFormat::IeeeFloat << WavAudioFormat(0xdead); + CORRADE_COMPARE(out.str(), "Audio::WavAudioFormat::IeeeFloat Audio::WavAudioFormat(0xdead)\n"); +} + }}} CORRADE_TEST_MAIN(Magnum::Audio::Test::WavImporterTest) diff --git a/src/MagnumPlugins/WavAudioImporter/Test/configure.h.cmake b/src/MagnumPlugins/WavAudioImporter/Test/configure.h.cmake index 8bcf9cc77..ae1369dd9 100644 --- a/src/MagnumPlugins/WavAudioImporter/Test/configure.h.cmake +++ b/src/MagnumPlugins/WavAudioImporter/Test/configure.h.cmake @@ -23,4 +23,4 @@ DEALINGS IN THE SOFTWARE. */ -#define WAVAUDIOIMPORTER_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" +#define WAVAUDIOIMPORTER_TEST_DIR "${WAVAUDIOIMPORTER_TEST_DIR}" diff --git a/src/MagnumPlugins/WavAudioImporter/Test/invalidDataChunk.wav b/src/MagnumPlugins/WavAudioImporter/Test/invalidDataChunk.wav new file mode 100644 index 000000000..13c98ead3 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/invalidDataChunk.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/invalidFactChunk.wav b/src/MagnumPlugins/WavAudioImporter/Test/invalidFactChunk.wav new file mode 100644 index 000000000..1b2f7bf1a Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/invalidFactChunk.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/invalidLength.wav b/src/MagnumPlugins/WavAudioImporter/Test/invalidLength.wav new file mode 100644 index 000000000..5c864de69 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/invalidLength.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/invalidPadding.wav b/src/MagnumPlugins/WavAudioImporter/Test/invalidPadding.wav new file mode 100644 index 000000000..2652873b9 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/invalidPadding.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/mono24.wav b/src/MagnumPlugins/WavAudioImporter/Test/mono24.wav new file mode 100644 index 000000000..4afeca1d1 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/mono24.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/mono32f.wav b/src/MagnumPlugins/WavAudioImporter/Test/mono32f.wav new file mode 100644 index 000000000..d9f2aa0ff Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/mono32f.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/mono4.wav b/src/MagnumPlugins/WavAudioImporter/Test/mono4.wav new file mode 100644 index 000000000..c7577a9e7 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/mono4.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/mono8.wav b/src/MagnumPlugins/WavAudioImporter/Test/mono8.wav new file mode 100644 index 000000000..c6fb50669 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/mono8.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/mono8ALaw.wav b/src/MagnumPlugins/WavAudioImporter/Test/mono8ALaw.wav new file mode 100644 index 000000000..80ed96f10 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/mono8ALaw.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/mono8MuLaw.wav b/src/MagnumPlugins/WavAudioImporter/Test/mono8MuLaw.wav new file mode 100644 index 000000000..e03211bfe Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/mono8MuLaw.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/mono8junk.wav b/src/MagnumPlugins/WavAudioImporter/Test/mono8junk.wav new file mode 100644 index 000000000..32480cbaa Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/mono8junk.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo12.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo12.wav new file mode 100644 index 000000000..755f6db27 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo12.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo16.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo16.wav new file mode 100644 index 000000000..f3860dc83 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo16.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo24.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo24.wav new file mode 100644 index 000000000..d3493cb4e Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo24.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo32.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo32.wav new file mode 100644 index 000000000..009dc66fb Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo32.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo32f.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo32f.wav new file mode 100644 index 000000000..e167301a8 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo32f.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo4.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo4.wav new file mode 100644 index 000000000..a11034614 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo4.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo64f.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo64f.wav new file mode 100644 index 000000000..ee9c65d25 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo64f.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo8ALaw.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo8ALaw.wav new file mode 100644 index 000000000..543cf4d00 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo8ALaw.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/stereo8MuLaw.wav b/src/MagnumPlugins/WavAudioImporter/Test/stereo8MuLaw.wav new file mode 100644 index 000000000..020ad2740 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/stereo8MuLaw.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/surround51Channel16.wav b/src/MagnumPlugins/WavAudioImporter/Test/surround51Channel16.wav new file mode 100644 index 000000000..e051095fa Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/surround51Channel16.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/Test/surround71Channel24.wav b/src/MagnumPlugins/WavAudioImporter/Test/surround71Channel24.wav new file mode 100644 index 000000000..23646e204 Binary files /dev/null and b/src/MagnumPlugins/WavAudioImporter/Test/surround71Channel24.wav differ diff --git a/src/MagnumPlugins/WavAudioImporter/WavHeader.cpp b/src/MagnumPlugins/WavAudioImporter/WavHeader.cpp new file mode 100644 index 000000000..a3df3b83a --- /dev/null +++ b/src/MagnumPlugins/WavAudioImporter/WavHeader.cpp @@ -0,0 +1,56 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "WavHeader.h" + +#include + +#include "Magnum/Magnum.h" + +namespace Magnum { namespace Audio { + +static_assert(sizeof(RiffChunk) == 8, "RiffChunk size is not 8 bytes"); +static_assert(sizeof(WavHeaderChunk) == 12, "WavHeaderChunk size is not 12 bytes"); +static_assert(sizeof(WavFormatChunk) == 24, "WavFormatChunk size is not 18 bytes"); + +Debug& operator<<(Debug& debug, const WavAudioFormat value) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case WavAudioFormat::value: return debug << "Audio::WavAudioFormat::" #value; + _c(Unknown) + _c(Pcm) + _c(AdPcm) + _c(IeeeFloat) + _c(ALaw) + _c(MuLaw) + _c(Extensible) + #undef _c + /* LCOV_EXCL_STOP */ + } + + return debug << "Audio::WavAudioFormat(" << Debug::nospace << reinterpret_cast(UnsignedShort(value)) << Debug::nospace << ")"; +} + +}} diff --git a/src/MagnumPlugins/WavAudioImporter/WavHeader.h b/src/MagnumPlugins/WavAudioImporter/WavHeader.h index 4948fea35..90e447008 100644 --- a/src/MagnumPlugins/WavAudioImporter/WavHeader.h +++ b/src/MagnumPlugins/WavAudioImporter/WavHeader.h @@ -5,6 +5,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 Vladimír Vondruš + Copyright © 2016 Alice Margatroid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,35 +27,55 @@ */ /** @file - * @brief Struct @ref Magnum::Audio::WavHeader + * @brief Struct @ref Magnum::Audio::RiffChunk, @ref Magnum::Audio::WavHeaderChunk, @ref Magnum::Audio::WavFormatChunk, enum @ref Magnum::Audio::WavAudioFormat */ -#include "Magnum/Types.h" +#include "MagnumPlugins/WavAudioImporter/WavImporter.h" namespace Magnum { namespace Audio { +/** @brief WAV audio format */ +enum class WavAudioFormat: UnsignedShort { + Unknown = 0x0000, /**< Unknown */ + Pcm = 0x0001, /**< PCM */ + AdPcm = 0x0002, /**< Adaptive Differential PCM */ + IeeeFloat = 0x0003, /**< IEEE Float */ + ALaw = 0x0006, /**< A-Law */ + MuLaw = 0x0007, /**< μ-Law */ + Extensible = 0xfffe /**< Extensible */ +}; + +#pragma pack(1) +/** @brief RIFF chunk */ +struct RiffChunk { + char chunkId[4]; /**< @brief chunk name (4 characters) */ + UnsignedInt chunkSize; /**< @brief size of chunk (does not include chunk header) */ +}; +#pragma pack() + #pragma pack(1) /** @brief WAV file header */ -struct WavHeader { - char chunkId[4]; /**< @brief `RIFF` characters */ - UnsignedInt chunkSize; /**< @brief Size of the rest of the file */ +struct WavHeaderChunk { + RiffChunk chunk; /**< @brief Starting RIFF chunk */ char format[4]; /**< @brief `WAVE` characters */ +}; +#pragma pack() - char subChunk1Id[4]; /**< @brief `fmt ` characters */ - UnsignedInt subChunk1Size; /**< @brief 16 for PCM */ - UnsignedShort audioFormat; /**< @brief 1 = PCM */ +#pragma pack(1) +/** @brief WAV 'fmt' header */ +struct WavFormatChunk { + RiffChunk chunk; /**< @brief Starting RIFF chunk */ + WavAudioFormat audioFormat; /**< @brief Audio format */ UnsignedShort numChannels; /**< @brief 1 = Mono, 2 = Stereo */ UnsignedInt sampleRate; /**< @brief Sample rate in Hz */ UnsignedInt byteRate; /**< @brief Bytes per second */ UnsignedShort blockAlign; /**< @brief Bytes per sample (all channels) */ UnsignedShort bitsPerSample; /**< @brief Bits per sample (one channel) */ - - char subChunk2Id[4]; /**< @brief `data` characters */ - UnsignedInt subChunk2Size; /**< @brief Size of the following data */ }; #pragma pack() -static_assert(sizeof(WavHeader) == 44, "WavHeader size is not 44 bytes"); +/** @debugoperatorenum{WavAudioFormat} */ +MAGNUM_WAVAUDIOIMPORTER_EXPORT Debug& operator<<(Debug& debug, WavAudioFormat value); }} diff --git a/src/MagnumPlugins/WavAudioImporter/WavImporter.cpp b/src/MagnumPlugins/WavAudioImporter/WavImporter.cpp index aa001e105..449effa49 100644 --- a/src/MagnumPlugins/WavAudioImporter/WavImporter.cpp +++ b/src/MagnumPlugins/WavAudioImporter/WavImporter.cpp @@ -3,6 +3,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 Vladimír Vondruš + Copyright © 2016 Alice Margatroid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -43,74 +44,171 @@ bool WavImporter::doIsOpened() const { return _data; } void WavImporter::doOpenData(Containers::ArrayView data) { /* Check file size */ - if(data.size() < sizeof(WavHeader)) { + if(data.size() < sizeof(WavHeaderChunk) + sizeof(WavFormatChunk) + sizeof(RiffChunk)) { Error() << "Audio::WavImporter::openData(): the file is too short:" << data.size() << "bytes"; return; } - /* Get header contents and fix endianness */ - WavHeader header(*reinterpret_cast(data.begin())); - Utility::Endianness::littleEndianInPlace(header.chunkSize, - header.subChunk1Size, header.audioFormat, header.numChannels, - header.sampleRate, header.byteRate, header.blockAlign, - header.bitsPerSample, header.subChunk2Size); - - /* Check file signature */ - if(std::strncmp(header.chunkId, "RIFF", 4) != 0 || - std::strncmp(header.format, "WAVE", 4) != 0 || - std::strncmp(header.subChunk1Id, "fmt ", 4) != 0 || - std::strncmp(header.subChunk2Id, "data", 4) != 0) { + /* Get the RIFF/WAV header */ + WavHeaderChunk header(*reinterpret_cast(data.begin())); + + /* Check RIFF/WAV file signature */ + if(std::strncmp(header.chunk.chunkId, "RIFF", 4) != 0 || + std::strncmp(header.format, "WAVE", 4) != 0) { Error() << "Audio::WavImporter::openData(): the file signature is invalid"; return; } + Utility::Endianness::littleEndianInPlace(header.chunk.chunkSize); + /* Check file size */ - if(header.chunkSize + 8 != data.size()) { + if(header.chunk.chunkSize < 36 || header.chunk.chunkSize + 8 != data.size()) { Error() << "Audio::WavImporter::openData(): the file has improper size, expected" - << header.chunkSize + 8 << "but got" << data.size(); + << header.chunk.chunkSize + 8 << "but got" << data.size(); + return; + } + + const RiffChunk* dataChunk = nullptr; + const WavFormatChunk* formatChunk = nullptr; + UnsignedInt dataChunkSize = 0; + + const UnsignedInt headerSize = sizeof(WavHeaderChunk); + UnsignedInt offset = 0; + + /* Skip any chunks that aren't the format or data chunk */ + while(headerSize + offset <= header.chunk.chunkSize) { + const RiffChunk* currChunk = reinterpret_cast(data.begin() + headerSize + offset); + offset += Utility::Endianness::littleEndian(currChunk->chunkSize) + sizeof(RiffChunk); + + if(std::strncmp(currChunk->chunkId, "fmt ", 4) == 0) { + if(formatChunk != nullptr) { + Error() << "Audio::WavImporter::openData(): the file contains too many format chunks"; + return; + } + + formatChunk = reinterpret_cast(currChunk); + + } else if(std::strncmp(currChunk->chunkId, "data", 4) == 0) { + if(dataChunk != nullptr) { + Error() << "Audio::WavImporter::openData(): the file contains too many data chunks"; + return; + } + + dataChunk = currChunk; + dataChunkSize = Utility::Endianness::littleEndian(currChunk->chunkSize); + + break; + } + } + + /* Make sure we actually got a format chunk */ + if(formatChunk == nullptr) { + Error() << "Audio::WavImporter::openData(): the file contains no format chunk"; + return; + } + + /* Make sure we actually got a data chunk */ + if(dataChunk == nullptr) { + Error() << "Audio::WavImporter::openData(): the file contains no data chunk"; return; } + /* Fix endianness on Format chunk */ + Utility::Endianness::littleEndianInPlace( + formatChunk->chunk.chunkSize, formatChunk->audioFormat, formatChunk->numChannels, + formatChunk->sampleRate, formatChunk->byteRate, formatChunk->blockAlign, + formatChunk->bitsPerSample); + /* Check PCM format */ - if(header.audioFormat != 1) { - Error() << "Audio::WavImporter::openData(): unsupported audio format" << header.audioFormat; + if(formatChunk->audioFormat == WavAudioFormat::Pcm) { + /* Decide about format */ + if(formatChunk->numChannels == 1 && formatChunk->bitsPerSample == 8) + _format = Buffer::Format::Mono8; + else if(formatChunk->numChannels == 1 && formatChunk->bitsPerSample == 16) + _format = Buffer::Format::Mono16; + else if(formatChunk->numChannels == 2 && formatChunk->bitsPerSample == 8) + _format = Buffer::Format::Stereo8; + else if(formatChunk->numChannels == 2 && formatChunk->bitsPerSample == 16) + _format = Buffer::Format::Stereo16; + else { + Error() << "Audio::WavImporter::openData(): PCM with unsupported channel count" + << formatChunk->numChannels << "with" << formatChunk->bitsPerSample + << "bits per sample"; + return; + } + + /* Check IEEE Float format */ + } else if(formatChunk->audioFormat == WavAudioFormat::IeeeFloat) { + if(formatChunk->numChannels == 1 && formatChunk->bitsPerSample == 32) + _format = Buffer::Format::MonoFloat; + else if(formatChunk->numChannels == 2 && formatChunk->bitsPerSample == 32) + _format = Buffer::Format::StereoFloat; + else if(formatChunk->numChannels == 1 && formatChunk->bitsPerSample == 64) + _format = Buffer::Format::MonoDouble; + else if(formatChunk->numChannels == 2 && formatChunk->bitsPerSample == 64) + _format = Buffer::Format::StereoDouble; + else { + Error() << "Audio::WavImporter::openData(): IEEE with unsupported channel count" + << formatChunk->numChannels << "with" << formatChunk->bitsPerSample + << "bits per sample"; + return; + } + + /* Check A-Law format */ + } else if(formatChunk->audioFormat == WavAudioFormat::ALaw) { + if(formatChunk->numChannels == 1) + _format = Buffer::Format::MonoALaw; + else if(formatChunk->numChannels == 2) + _format = Buffer::Format::StereoALaw; + else { + Error() << "Audio::WavImporter::openData(): ALaw with unsupported channel count" + << formatChunk->numChannels << "with" << formatChunk->bitsPerSample + << "bits per sample"; + return; + } + + /* Check μ-Law format */ + } else if(formatChunk->audioFormat == WavAudioFormat::MuLaw) { + if(formatChunk->numChannels == 1) + _format = Buffer::Format::MonoMuLaw; + else if(formatChunk->numChannels == 2) + _format = Buffer::Format::StereoMuLaw; + else { + Error() << "Audio::WavImporter::openData(): MuLaw with unsupported channel count" + << formatChunk->numChannels << "with" << formatChunk->bitsPerSample + << "bits per sample"; + return; + } + + /* Unknown/unimplemented format */ + } else { + Error() << "Audio::WavImporter::openData(): unsupported format" << formatChunk->audioFormat; return; } - /* Verify more things */ - if(header.subChunk1Size != 16 || - header.subChunk2Size + 44 != data.size() || - header.blockAlign != header.numChannels*header.bitsPerSample/8 || - header.byteRate != header.sampleRate*header.blockAlign) { - Error() << "Audio::WavImporter::openData(): the file is corrupted"; + /* Size sanity checks */ + if(headerSize + offset > data.size()) { + Error() << "Audio::WavImporter::openData(): file size doesn't match computed size"; return; } - /* Decide about format */ - if(header.numChannels == 1 && header.bitsPerSample == 8) - _format = Buffer::Format::Mono8; - else if(header.numChannels == 1 && header.bitsPerSample == 16) - _format = Buffer::Format::Mono16; - else if(header.numChannels == 2 && header.bitsPerSample == 8) - _format = Buffer::Format::Stereo8; - else if(header.numChannels == 2 && header.bitsPerSample == 16) - _format = Buffer::Format::Stereo16; - else { - Error() << "Audio::WavImporter::openData(): unsupported channel count" - << header.numChannels << "with" << header.bitsPerSample - << "bits per sample"; + /* Format sanity checks */ + if(formatChunk->blockAlign != formatChunk->numChannels * formatChunk->bitsPerSample / 8 || + formatChunk->byteRate != formatChunk->sampleRate * formatChunk->blockAlign) { + Error() << "Audio::WavImporter::openData(): the file is corrupted"; return; } /* Save frequency */ - _frequency = header.sampleRate; + _frequency = formatChunk->sampleRate; /** @todo Convert the data from little endian too */ CORRADE_INTERNAL_ASSERT(!Utility::Endianness::isBigEndian()); /* Copy the data */ - _data = Containers::Array(header.subChunk2Size); - std::copy(data.begin()+sizeof(WavHeader), data.end(), _data.begin()); + const char* dataChunkPtr = reinterpret_cast(dataChunk + 1); + _data = Containers::Array(dataChunkSize); + std::copy(dataChunkPtr, dataChunkPtr+dataChunkSize, _data.begin()); return; } diff --git a/src/MagnumPlugins/WavAudioImporter/WavImporter.h b/src/MagnumPlugins/WavAudioImporter/WavImporter.h index 3300821e9..83dff2d04 100644 --- a/src/MagnumPlugins/WavAudioImporter/WavImporter.h +++ b/src/MagnumPlugins/WavAudioImporter/WavImporter.h @@ -5,6 +5,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 Vladimír Vondruš + Copyright © 2016 Alice Margatroid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -33,14 +34,36 @@ #include "Magnum/Audio/AbstractImporter.h" +#include "MagnumPlugins/WavAudioImporter/configure.h" + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_WAVAUDIOIMPORTER_BUILD_STATIC + #if defined(WavAudioImporter_EXPORTS) || defined(WavAudioImporterObjects_EXPORTS) + #define MAGNUM_WAVAUDIOIMPORTER_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define MAGNUM_WAVAUDIOIMPORTER_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define MAGNUM_WAVAUDIOIMPORTER_EXPORT CORRADE_VISIBILITY_STATIC +#endif +#define MAGNUM_WAVAUDIOIMPORTER_LOCAL CORRADE_VISIBILITY_LOCAL +#endif + namespace Magnum { namespace Audio { /** @brief WAV importer plugin -Supports mono and stereo PCM files with 8 or 16 bits per channel. The files are -imported with @ref Buffer::Format::Mono8, @ref Buffer::Format::Mono16, -@ref Buffer::Format::Stereo8 or @ref Buffer::Format::Stereo16, respectively. +Supports mono and stereo files of the following formats: + +- 8 bit per channel PCM, imported as @ref Buffer::Format::Mono8 and @ref Buffer::Format::Stereo8 +- 16 bit per channel PCM, imported as @ref Buffer::Format::Mono16 and @ref Buffer::Format::Stereo16 +- 32-bit IEEE Float, imported as @ref Buffer::Format::MonoFloat / @ref Buffer::Format::StereoFloat +- 64-bit IEEE Float, imported as @ref Buffer::Format::MonoDouble / @ref Buffer::Format::StereoDouble +- A-Law, imported as @ref Buffer::Format::MonoALaw / @ref Buffer::Format::StereoALaw +- μ-Law, imported as @ref Buffer::Format::MonoMuLaw / @ref Buffer::Format::StereoMuLaw + +Multi-channel formats are not supported. This plugin is built if `WITH_WAVAUDIOIMPORTER` is enabled when building Magnum. To use dynamic plugin, you need to load `WavAudioImporter` plugin @@ -49,7 +72,7 @@ dependency of another plugin, you need to request `WavAudioImporter` component of `Magnum` package in CMake and link to `Magnum::WavAudioImporter` target. See @ref building, @ref cmake and @ref plugins for more information. */ -class WavImporter: public AbstractImporter { +class MAGNUM_WAVAUDIOIMPORTER_EXPORT WavImporter: public AbstractImporter { public: /** @brief Default constructor */ explicit WavImporter(); @@ -58,14 +81,14 @@ class WavImporter: public AbstractImporter { explicit WavImporter(PluginManager::AbstractManager& manager, std::string plugin); private: - Features doFeatures() const override; - bool doIsOpened() const override; - void doOpenData(Containers::ArrayView data) override; - void doClose() override; - - Buffer::Format doFormat() const override; - UnsignedInt doFrequency() const override; - Containers::Array doData() override; + MAGNUM_WAVAUDIOIMPORTER_LOCAL Features doFeatures() const override; + MAGNUM_WAVAUDIOIMPORTER_LOCAL bool doIsOpened() const override; + MAGNUM_WAVAUDIOIMPORTER_LOCAL void doOpenData(Containers::ArrayView data) override; + MAGNUM_WAVAUDIOIMPORTER_LOCAL void doClose() override; + + MAGNUM_WAVAUDIOIMPORTER_LOCAL Buffer::Format doFormat() const override; + MAGNUM_WAVAUDIOIMPORTER_LOCAL UnsignedInt doFrequency() const override; + MAGNUM_WAVAUDIOIMPORTER_LOCAL Containers::Array doData() override; Containers::Array _data; Buffer::Format _format; diff --git a/src/MagnumPlugins/WavAudioImporter/configure.h.cmake b/src/MagnumPlugins/WavAudioImporter/configure.h.cmake new file mode 100644 index 000000000..511a9a0a6 --- /dev/null +++ b/src/MagnumPlugins/WavAudioImporter/configure.h.cmake @@ -0,0 +1,26 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#cmakedefine MAGNUM_WAVAUDIOIMPORTER_BUILD_STATIC diff --git a/src/Magnum/dummy.cpp b/src/dummy.cpp similarity index 100% rename from src/Magnum/dummy.cpp rename to src/dummy.cpp diff --git a/toolchains b/toolchains index db1c8163e..2867dd164 160000 --- a/toolchains +++ b/toolchains @@ -1 +1 @@ -Subproject commit db1c8163e6a43bd8a77029b7080d3a802870b57d +Subproject commit 2867dd16455ed010a4a495a440a7c0d3bc2b43f1