Browse Source

Split the OpenGL layer out, pt 9: generic pixel formats.

This is quite big, so:

 * There are new Magnum::PixelFormat and Magnum::CompressedPixelFormat
   enums, which contain generic API-independent formats. In particular,
   PixelFormat replaces GL::PixelFormat and GL::PixelType with a single
   value.
 * There's GL::pixelFormat(), GL::pixelType(),
   GL::compressedPixelFormat() to convert the generic enums to
   GL-specific. The mapping is only in one direction, done with a lookup
   table (generic enums are indices to that table).
 * GL classes taking the formats directly (such as GL::BufferImage) have
   overloads that take both the GL-specific and generic format.
 * The generic Image, CompressedImage, ImageView, CompressedImageView,
   and Trade::ImageData classes now accept the generic formats
   first-class. However, it's also possible to store an
   implementation-specific value to cover cases where a generic format
   enum doesn't have support for a particular format. This is done by
   wrapping the value using pixelFormatWrap() or
   compressedPixelFormatWrap(). Particular GPU APIs then assume it's
   their implementation-specific value and extract the value back using
   pixelFormatUnwrap() or compressedPixelFormatUnwrap(). There's also an
   isPixelFormatImplementationSpecific() and
   isCompressedPixelFormatImplementationSpecific() that distinguishes
   these values.
 * Many operations need pixel size and in order to have it even for
   implementation-specific formats, a corresponding pixelSize()
   overload is found via ADL on construction and the calculated size
   stored along the format. Previously the pixel size was only
   calculated on demand, but that's not possible now. In case such
   overload is not available, it's possible to pass pixel size manually
   as well.
 * In order to support the GL format+type pair, Image, ImageView and
   Trade::ImageData, there's now an additional untyped formatExtra()
   field that holds the second value.
 * The CompressedPixelStorage class is now unconditionally available on
   all targets, including OpenGL ES and WebGL. However, on OpenGL ES the
   GL APIs expect that it's all at default values.

I attempted to preserve backwards compatibility as much as possible:

 * The PixelFormat and CompressedPixelFormat enum now contains generic
   API-independent values. The GL-specific formats are present there,
   but marked as deprecated. Use either the generic values or
   GL::PixelFormat (togehter with GL::PixelType) and
   GL::CompressedPixelFormat instead. There's a lot of ugliness caused
   by this, but seems to work well.
 * *Image::type() functions are deprecated as they were too
   GL-specific. Use formatExtra() and cast it to GL::PixelType instead.
 * Image constructors take templated format or format+extra arguments,
   so passing GL-specific values to them should still work.
pull/233/head
Vladimír Vondruš 8 years ago
parent
commit
6d41597d1d
  1. 58
      doc/changelog.dox
  2. 8
      doc/snippets/CMakeLists.txt
  3. 179
      doc/snippets/Magnum.cpp
  4. 54
      doc/snippets/MagnumGL.cpp
  5. 70
      doc/snippets/MagnumTrade.cpp
  6. 66
      src/Magnum/CMakeLists.txt
  7. 5
      src/Magnum/GL/AbstractFramebuffer.cpp
  8. 72
      src/Magnum/GL/AbstractTexture.cpp
  9. 66
      src/Magnum/GL/BufferImage.cpp
  10. 479
      src/Magnum/GL/BufferImage.h
  11. 69
      src/Magnum/GL/CMakeLists.txt
  12. 27
      src/Magnum/GL/CubeMapTexture.cpp
  13. 6
      src/Magnum/GL/Implementation/RendererState.cpp
  14. 32
      src/Magnum/GL/Implementation/compressedPixelFormatMapping.hpp
  15. 140
      src/Magnum/GL/Implementation/pixelFormatMapping.hpp
  16. 126
      src/Magnum/GL/PixelFormat.cpp
  17. 142
      src/Magnum/GL/PixelFormat.h
  18. 20
      src/Magnum/GL/Test/BufferImageGLTest.cpp
  19. 4
      src/Magnum/GL/Test/CMakeLists.txt
  20. 74
      src/Magnum/GL/Test/FormatTest.cpp
  21. 548
      src/Magnum/GL/Test/PixelFormatTest.cpp
  22. 2
      src/Magnum/GL/visibility.h
  23. 32
      src/Magnum/Image.cpp
  24. 505
      src/Magnum/Image.h
  25. 26
      src/Magnum/ImageView.cpp
  26. 579
      src/Magnum/ImageView.h
  27. 7
      src/Magnum/Magnum.h
  28. 369
      src/Magnum/PixelFormat.cpp
  29. 1115
      src/Magnum/PixelFormat.h
  30. 39
      src/Magnum/PixelStorage.h
  31. 3
      src/Magnum/Test/CMakeLists.txt
  32. 216
      src/Magnum/Test/PixelFormatTest.cpp
  33. 34
      src/Magnum/Trade/ImageData.cpp
  34. 251
      src/Magnum/Trade/ImageData.h

58
doc/changelog.dox

@ -48,6 +48,14 @@ See also:
@subsection changelog-latest-new New features @subsection changelog-latest-new New features
- New @ref PixelFormat / @ref CompressedPixelFormat enums containing generic
API-independent pixel formats, together with @ref pixelSize(),
@ref pixelFormatWrap() / @ref pixelFormatUnwrap(),
@ref compressedPixelFormatWrap() / @ref compressedPixelFormatUnwrap() and @ref isPixelFormatImplementationSpecific() /
@ref isCompressedPixelFormatImplementationSpecific() utilities now used by
@ref Image / @ref CompressedImage and @ref ImageView /
@ref CompressedImageView instead of the GL-specific formats
@subsubsection changelog-latest-new-math Math library @subsubsection changelog-latest-new-math Math library
- Added @ref Math::isInf(), @ref Math::isNan() - Added @ref Math::isInf(), @ref Math::isNan()
@ -56,6 +64,11 @@ See also:
- A new library that now contains wrappers for the OpenGL family of graphics - A new library that now contains wrappers for the OpenGL family of graphics
APIs, separated from the core Magnum library APIs, separated from the core Magnum library
- New @ref GL::hasPixelFormat(), @ref GL::pixelFormat(), @ref GL::pixelType(),
@ref GL::hasCompressedPixelFormat(), @ref compressedPixelFormat() utilities
for converting generic @ref PixelFormat / @ref CompressedPixelFormat to
GL-specific @ref GL::PixelFormat, @ref GL::PixelType and
@ref GL::CompressedPixelFormat values
- Initial support for OpenGL ES 3.2 and OpenGL 4.6 - Initial support for OpenGL ES 3.2 and OpenGL 4.6
- New OpenGL extension support: - New OpenGL extension support:
- @extension{ARB,texture_filter_anisotropic} - @extension{ARB,texture_filter_anisotropic}
@ -86,6 +99,13 @@ See also:
- Debug output operator for @ref Trade::PhongMaterialData::Flag and - Debug output operator for @ref Trade::PhongMaterialData::Flag and
@ref Trade::PhongMaterialData::Flags @ref Trade::PhongMaterialData::Flags
@subsection changelog-latest-changes Changes and improvements
- The @ref CompressedPixelStorage class and related APIs are now available
on all targets including OpenGL ES and WebGL, however at the moment, until
a compatibility code path is implemented, the @ref GL library expects that
all parameters are at their defaults.
@subsection changelog-latest-buildsystem Build system @subsection changelog-latest-buildsystem Build system
- All plugin interfaces now implement - All plugin interfaces now implement
@ -128,12 +148,20 @@ See also:
@ref Magnum namespace were moved to @ref Magnum/GL directory and @ref Magnum namespace were moved to @ref Magnum/GL directory and
@ref Magnum::GL namespace. See their documentation for information about @ref Magnum::GL namespace. See their documentation for information about
particular files, classes, enums, typedefs, values and functions. particular files, classes, enums, typedefs, values and functions.
- The @ref PixelFormat and @ref CompressedPixelFormat enum now contains
generic API-independent values. The GL-specific formats are present there,
but marked as deprecated. Use either the generic values or
@ref GL::PixelFormat (together with @ref GL::PixelType) and
@ref GL::CompressedPixelFormat instead.
- @ref PixelStorage::pixelSize() was deprecated, use @ref GL::pixelSize() - @ref PixelStorage::pixelSize() was deprecated, use @ref GL::pixelSize()
instead or @ref Magnum::pixelSize() instead
- `PixelStorage::dataProperties(GL::PixelFormat, GL::PixelSize, const Vector3i&)` - `PixelStorage::dataProperties(GL::PixelFormat, GL::PixelSize, const Vector3i&)`
was deprecated for being too GL-specific, use was deprecated for being too GL-specific, use
@ref PixelStorage::dataProperties(std::size_t, const Vector3i&) const @ref PixelStorage::dataProperties(std::size_t, const Vector3i&) const
together with @ref GL::pixelSize() instead together with @ref GL::pixelSize() instead
- `Image*::type()` functions are deprecated as these are too GL-specific. The
second format specifier is now available through @ref Image::formatExtra(),
@ref ImageView::formatExtra() and @ref Trade::ImageData::formatExtra()
- `Audio::Buffer::Format` is deprecated, use `Audio::BufferFormat` instead - `Audio::Buffer::Format` is deprecated, use `Audio::BufferFormat` instead
- `setData()` functions in the @ref Image and @ref CompressedImage classes - `setData()` functions in the @ref Image and @ref CompressedImage classes
are deprecated because they don't offer anything extra over simple are deprecated because they don't offer anything extra over simple
@ -185,6 +213,34 @@ See also:
to the complexity of this change, no backwards compatibility is provided. to the complexity of this change, no backwards compatibility is provided.
- The `magnum-info` utility was renamed to @ref magnum-gl-info. No backwards - The `magnum-info` utility was renamed to @ref magnum-gl-info. No backwards
compatibility symlinks or aliases are provided. compatibility symlinks or aliases are provided.
- @ref ImageView and @ref CompressedImageView methods are no longer
@cpp constexpr @ce. It might be possible to have them @cpp constexpr @ce in
C++14, but the resulting increase in maintenance costs and compile times is
not worth it.
- `PixelFormat` has been moved verbatim to @ref GL::PixelFormat and there's a
new @ref Magnum::PixelFormat enum for generic pixel formats. It contains
(deprecated) @ref GL::PixelFormat values for covering most of backwards
compatibility, but code that relies on these two types being the same may
break. In particular, @ref GL::BufferImage::format() now returns
@ref GL::PixelFormat instead of @ref Magnum::PixelFormat, code depending on
the return type being implicitly convertible to @ref Magnum::PixelFormat
may break. In all other cases, @ref Image::format() "Image*::format()"
returns @ref Magnum::PixelFormat.
- `CompressedPixelFormat` has been moved verbatim to
@ref GL::CompressedPixelFormat and there's a new
@ref Magnum::CompressedPixelFormat enum for generic pixel formats. It
contains (deprecated) @ref GL::CompressedPixelFormat values for covering
most of backwards compatibility, but code that relies on these two types
being the same may break. In particular,
@ref GL::CompressedBufferImage::format() now returns
@ref GL::CompressedPixelFormat instead of @ref Magnum::CompressedPixelFormat,
code depending on the return type being implicitly convertible to
@ref Magnum::CompressedPixelFormat may break. In all other cases,
@ref CompressedImage::format() "CompressedImage*::format()"
returns @ref Magnum::CompressedPixelFormat.
- The @ref Image::pixelSize(), @ref ImageView::pixelSize(),
@ref Trade::ImageData::pixelSize() and @ref BufferImage::pixelSize()
functions now return @ref UnsignedInt instead of @cpp std::size_t @ce.
- Removed `PixelStorage::setSwapBytes()`, as every Magnum API dealing with - Removed `PixelStorage::setSwapBytes()`, as every Magnum API dealing with
images basically only asserted that it's not set. Use images basically only asserted that it's not set. Use
@ref Corrade::Utility::Endianness instead. @ref Corrade::Utility::Endianness instead.

8
doc/snippets/CMakeLists.txt

@ -40,6 +40,7 @@ endif()
add_library(snippets-Magnum STATIC add_library(snippets-Magnum STATIC
plugins.cpp plugins.cpp
Magnum.cpp
MagnumMath.cpp) MagnumMath.cpp)
target_link_libraries(snippets-Magnum PRIVATE Magnum) target_link_libraries(snippets-Magnum PRIVATE Magnum)
set_target_properties(snippets-Magnum PROPERTIES FOLDER "Magnum/doc/snippets") set_target_properties(snippets-Magnum PROPERTIES FOLDER "Magnum/doc/snippets")
@ -54,6 +55,13 @@ if(WITH_GL)
set_target_properties(snippets-MagnumGL PROPERTIES FOLDER "Magnum/doc/snippets") set_target_properties(snippets-MagnumGL PROPERTIES FOLDER "Magnum/doc/snippets")
endif() endif()
if(WITH_TRADE)
add_library(snippets-MagnumTrade STATIC
MagnumTrade.cpp)
target_link_libraries(snippets-MagnumTrade PRIVATE MagnumTrade)
set_target_properties(snippets-MagnumTrade PROPERTIES FOLDER "Magnum/doc/snippets")
endif()
find_package(Corrade COMPONENTS TestSuite) find_package(Corrade COMPONENTS TestSuite)
if(WITH_DEBUGTOOLS) if(WITH_DEBUGTOOLS)

179
doc/snippets/Magnum.cpp

@ -0,0 +1,179 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/Image.h"
#include "Magnum/PixelFormat.h"
#ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/PixelFormat.h"
#include "Magnum/GL/Texture.h"
#endif
using namespace Magnum;
using namespace Magnum::Math::Literals;
int main() {
{
char data[3];
/* [ImageView-usage] */
ImageView2D image{PixelFormat::RGBA8Unorm, {512, 256}, data};
/* [ImageView-usage] */
}
{
char evenFrameData[3], oddFrameData[3];
/* [ImageView-usage-streaming] */
ImageView2D frame{PixelFormat::RGBA8Unorm, {512, 256}};
frame.setData(evenFrameData);
// Use even frame data ...
frame.setData(oddFrameData);
// Use odd frame data ...
/* [ImageView-usage-streaming] */
}
{
char data[3];
/* [ImageView-usage-storage] */
ImageView2D image{
PixelStorage{}
.setRowLength(75)
.setAlignment(4)
.setSkip({25, 25, 0}),
PixelFormat::RGBA8Unorm, {25, 25}, data};
/* [ImageView-usage-storage] */
}
#ifdef MAGNUM_TARGET_GL
{
char data[3];
/* [ImageView-usage-gl] */
ImageView2D image{GL::PixelFormat::DepthComponent,
GL::PixelType::UnsignedInt, {512, 256}, data};
/* [ImageView-usage-gl] */
/* [ImageView-usage-gl-extract] */
auto format = pixelFormatUnwrap<GLenum>(image.format());
auto type = GLenum(image.formatExtra());
/* [ImageView-usage-gl-extract] */
static_cast<void>(format);
static_cast<void>(type);
}
#endif
{
char data[3];
#define MTLPixelFormatRGBA8Unorm_sRGB 71
/* [ImageView-usage-metal] */
/* Default pixel storage, 8-bit sRGB + alpha, four bytes per pixel */
ImageView2D view{{}, MTLPixelFormatRGBA8Unorm_sRGB, {}, 4, {256, 256}, data};
/* [ImageView-usage-metal] */
}
{
char data[3];
/* [CompressedImageView-usage] */
CompressedImageView2D image{CompressedPixelFormat::Bc1RGBUnorm,
{512, 256}, data};
/* [CompressedImageView-usage] */
}
{
char evenFrameData[3], oddFrameData[3];
/* [CompressedImageView-usage-streaming] */
CompressedImageView2D frame{CompressedPixelFormat::Bc1RGBUnorm, {512, 256}};
frame.setData(evenFrameData);
// Use even frame data ...
frame.setData(oddFrameData);
// Use odd frame data ...
/* [CompressedImageView-usage-streaming] */
}
{
char data[3];
/* [CompressedImageView-usage-storage] */
CompressedImageView2D image{
CompressedPixelStorage{}
.setRowLength(64)
.setCompressedBlockSize({4, 4, 1})
.setCompressedBlockDataSize(8)
.setSkip({32, 32, 0}),
CompressedPixelFormat::Bc1RGBUnorm, {32, 32}, data};
/* [CompressedImageView-usage-storage] */
}
#if defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES)
{
char data[3];
/* [CompressedImageView-usage-gl] */
CompressedImageView2D image{GL::CompressedPixelFormat::SignedRGRgtc2,
{512, 256}, data};
/* [CompressedImageView-usage-gl] */
/* [CompressedImageView-usage-gl-extract] */
auto format = compressedPixelFormatUnwrap<GLenum>(image.format());
/* [CompressedImageView-usage-gl-extract] */
static_cast<void>(format);
}
#endif
{
/* [Image-usage] */
Containers::Array<char> data;
Image2D image{PixelFormat::RGBA8Unorm, {512, 256}, std::move(data)};
/* [Image-usage] */
}
#if defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES)
{
/* [Image-usage-query] */
GL::Texture2D texture;
Image2D image = texture.image(0, {GL::PixelFormat::DepthComponent,
GL::PixelType::UnsignedInt});
/* [Image-usage-query] */
}
#endif
{
/* [CompressedImage-usage] */
Containers::Array<char> data;
CompressedImage2D image{CompressedPixelFormat::Bc1RGBUnorm,
{512, 256}, std::move(data)};
/* [CompressedImage-usage] */
}
#if defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES)
{
/* [CompressedImage-usage-query] */
GL::Texture2D texture;
CompressedImage2D image = texture.compressedImage(0, {});
/* [CompressedImage-usage-query] */
}
#endif
}

54
doc/snippets/MagnumGL.cpp

@ -475,6 +475,60 @@ Buffer vertices{Buffer::TargetHint::Array},
/* [Buffer-webgl] */ /* [Buffer-webgl] */
} }
#ifndef MAGNUM_TARGET_GLES2
{
char data[3];
/* [BufferImage-usage] */
GL::BufferImage2D image{GL::PixelFormat::RGBA, GL::PixelType::UnsignedByte,
{512, 256}, data, GL::BufferUsage::StaticDraw};
/* [BufferImage-usage] */
}
{
/* [BufferImage-usage-wrap] */
GL::Buffer buffer;
GL::BufferImage2D image{GL::PixelFormat::RGBA, GL::PixelType::UnsignedByte,
{512, 256}, std::move(buffer), 524288};
/* [BufferImage-usage-wrap] */
}
#ifndef MAGNUM_TARGET_GLES
{
/* [BufferImage-usage-query] */
GL::Texture2D texture;
GL::BufferImage2D image = texture.image(0, {GL::PixelFormat::RGBA,
GL::PixelType::UnsignedByte}, GL::BufferUsage::StaticRead);
/* [BufferImage-usage-query] */
}
#endif
{
char data[3];
/* [CompressedBufferImage-usage] */
GL::CompressedBufferImage2D image{GL::CompressedPixelFormat::RGBS3tcDxt1,
{512, 256}, data, GL::BufferUsage::StaticDraw};
/* [CompressedBufferImage-usage] */
}
{
/* [CompressedBufferImage-usage-wrap] */
GL::Buffer buffer;
GL::CompressedBufferImage2D image{GL::CompressedPixelFormat::RGBS3tcDxt1,
{512, 256}, std::move(buffer), 65536};
/* [CompressedBufferImage-usage-wrap] */
}
#ifndef MAGNUM_TARGET_GLES
{
/* [CompressedBufferImage-usage-query] */
GL::Texture2D texture;
GL::CompressedBufferImage2D image = texture.compressedImage(0, {},
GL::BufferUsage::StaticRead);
/* [CompressedBufferImage-usage-query] */
}
#endif
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
{ {
/* [BufferTexture-usage] */ /* [BufferTexture-usage] */

70
doc/snippets/MagnumTrade.cpp

@ -0,0 +1,70 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/PixelFormat.h"
#include "Magnum/Trade/AbstractImporter.h"
#include "Magnum/Trade/ImageData.h"
#ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/Texture.h"
#endif
using namespace Magnum;
using namespace Magnum::Math::Literals;
int main() {
{
/* [ImageData-construction] */
Containers::Array<char> data;
Trade::ImageData2D image{PixelFormat::RGB8Unorm, {32, 32}, std::move(data)};
/* [ImageData-construction] */
}
{
/* [ImageData-construction-compressed] */
Containers::Array<char> data;
Trade::ImageData2D image{CompressedPixelFormat::Bc1RGBUnorm,
{32, 32}, std::move(data)};
/* [ImageData-construction-compressed] */
}
#ifdef MAGNUM_TARGET_GL
{
/* [ImageData-usage] */
std::unique_ptr<Trade::AbstractImporter> importer;
Containers::Optional<Trade::ImageData2D> image = importer->image2D(0);
if(!image) Fatal{} << "Oopsie!";
GL::Texture2D texture;
// ...
if(!image->isCompressed())
texture.setSubImage(0, {}, *image);
else
texture.setCompressedSubImage(0, {}, *image);
/* [ImageData-usage] */
}
#endif
}

66
src/Magnum/CMakeLists.txt

@ -28,10 +28,15 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake
# Files shared between main library and unit test library # Files shared between main library and unit test library
set(Magnum_SRCS set(Magnum_SRCS
Image.cpp
ImageView.cpp
PixelStorage.cpp PixelStorage.cpp
Resource.cpp Resource.cpp
Timeline.cpp) Timeline.cpp)
set(Magnum_GracefulAssert_SRCS
PixelFormat.cpp)
set(Magnum_HEADERS set(Magnum_HEADERS
AbstractResourceLoader.h AbstractResourceLoader.h
Array.h Array.h
@ -39,6 +44,7 @@ set(Magnum_HEADERS
Image.h Image.h
ImageView.h ImageView.h
Magnum.h Magnum.h
PixelFormat.h
PixelStorage.h PixelStorage.h
Resource.h Resource.h
ResourceManager.h ResourceManager.h
@ -65,7 +71,6 @@ if(WITH_GL AND BUILD_DEPRECATED)
Mesh.h Mesh.h
MeshView.h MeshView.h
OpenGL.h OpenGL.h
PixelFormat.h
Renderbuffer.h Renderbuffer.h
RenderbufferFormat.h RenderbufferFormat.h
Renderer.h Renderer.h
@ -127,7 +132,7 @@ set(MagnumMath_SRCS
Math/Packing.cpp Math/Packing.cpp
Math/instantiation.cpp) Math/instantiation.cpp)
# Objects shared between main and test library # Objects shared between main and math test library
add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS}) add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS})
target_include_directories(MagnumMathObjects PUBLIC target_include_directories(MagnumMathObjects PUBLIC
${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src
@ -141,11 +146,32 @@ if(NOT BUILD_STATIC OR BUILD_STATIC_PIC)
endif() endif()
set_target_properties(MagnumMathObjects PROPERTIES FOLDER "Magnum/Math") set_target_properties(MagnumMathObjects PROPERTIES FOLDER "Magnum/Math")
# Main library # Objects shared between main and test library
add_library(Magnum ${SHARED_OR_STATIC} add_library(MagnumObjects OBJECT
${Magnum_SRCS} ${Magnum_SRCS}
${Magnum_HEADERS} ${Magnum_HEADERS}
$<TARGET_OBJECTS:MagnumMathObjects>) ${Magnum_PRIVATE_HEADERS})
target_include_directories(MagnumObjects PUBLIC
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src
$<TARGET_PROPERTY:Corrade::Utility,INTERFACE_INCLUDE_DIRECTORIES>)
if(BUILD_DEPRECATED AND TARGET_GL) # TODO: remove once compat gets dropped
target_include_directories(MagnumObjects PUBLIC
${PROJECT_SOURCE_DIR}/src/MagnumExternal/OpenGL)
endif()
if(NOT BUILD_STATIC)
target_compile_definitions(MagnumObjects PRIVATE "MagnumObjects_EXPORTS")
endif()
if(NOT BUILD_STATIC OR BUILD_STATIC_PIC)
set_target_properties(MagnumObjects PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
set_target_properties(MagnumObjects PROPERTIES FOLDER "Magnum")
# Main library
add_library(Magnum ${SHARED_OR_STATIC}
$<TARGET_OBJECTS:MagnumMathObjects>
$<TARGET_OBJECTS:MagnumObjects>
${Magnum_GracefulAssert_SRCS})
set_target_properties(Magnum PROPERTIES set_target_properties(Magnum PROPERTIES
DEBUG_POSTFIX "-d" DEBUG_POSTFIX "-d"
FOLDER "Magnum") FOLDER "Magnum")
@ -157,6 +183,10 @@ endif()
target_include_directories(Magnum PUBLIC target_include_directories(Magnum PUBLIC
${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src) ${PROJECT_BINARY_DIR}/src)
if(BUILD_DEPRECATED AND TARGET_GL) # TODO: remove once compat gets dropped
target_include_directories(Magnum PUBLIC
${PROJECT_SOURCE_DIR}/src/MagnumExternal/OpenGL)
endif()
target_link_libraries(Magnum PUBLIC target_link_libraries(Magnum PUBLIC
Corrade::Utility) Corrade::Utility)
@ -215,7 +245,7 @@ if(WITH_TRADE)
endif() endif()
if(BUILD_TESTS) if(BUILD_TESTS)
# Library with graceful assert for testing # Math library with graceful assert for testing
add_library(MagnumMathTestLib ${SHARED_OR_STATIC} add_library(MagnumMathTestLib ${SHARED_OR_STATIC}
$<TARGET_OBJECTS:MagnumMathObjects> $<TARGET_OBJECTS:MagnumMathObjects>
${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details ${PROJECT_SOURCE_DIR}/src/dummy.cpp) # XCode workaround, see file comment for details
@ -228,10 +258,32 @@ if(BUILD_TESTS)
FOLDER "Magnum/Math") FOLDER "Magnum/Math")
target_link_libraries(MagnumMathTestLib Corrade::Utility) target_link_libraries(MagnumMathTestLib Corrade::Utility)
# Library with graceful assert for testing
add_library(MagnumTestLib ${SHARED_OR_STATIC}
$<TARGET_OBJECTS:MagnumMathObjects>
$<TARGET_OBJECTS:MagnumObjects>
${Magnum_GracefulAssert_SRCS})
target_include_directories(MagnumTestLib PUBLIC
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src)
if(BUILD_DEPRECATED AND TARGET_GL) # TODO: remove once compat gets dropped
target_include_directories(MagnumTestLib PUBLIC
${PROJECT_SOURCE_DIR}/src/MagnumExternal/OpenGL)
endif()
target_compile_definitions(MagnumTestLib PRIVATE
"CORRADE_GRACEFUL_ASSERT" "Magnum_EXPORTS")
set_target_properties(MagnumTestLib PROPERTIES
DEBUG_POSTFIX "-d"
FOLDER "Magnum")
if(BUILD_STATIC_PIC)
set_target_properties(MagnumTestLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
target_link_libraries(MagnumTestLib PUBLIC Corrade::Utility)
# On Windows we need to install first and then run the tests to avoid "DLL # On Windows we need to install first and then run the tests to avoid "DLL
# not found" hell, thus we need to install this too # not found" hell, thus we need to install this too
if(CORRADE_TARGET_WINDOWS AND NOT CMAKE_CROSSCOMPILING AND NOT BUILD_STATIC) if(CORRADE_TARGET_WINDOWS AND NOT CMAKE_CROSSCOMPILING AND NOT BUILD_STATIC)
install(TARGETS MagnumMathTestLib install(TARGETS MagnumMathTestLib MagnumTestLib
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})

5
src/Magnum/GL/AbstractFramebuffer.cpp

@ -35,6 +35,7 @@
#include "Magnum/GL/CubeMapTextureArray.h" #include "Magnum/GL/CubeMapTextureArray.h"
#endif #endif
#include "Magnum/GL/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/GL/PixelFormat.h"
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
#include "Magnum/GL/RectangleTexture.h" #include "Magnum/GL/RectangleTexture.h"
#endif #endif
@ -308,12 +309,12 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, Image2D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
#endif #endif
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer->applyPixelStoragePack(image.storage());
(Context::current().state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), data.size(), data (Context::current().state().framebuffer->readImplementation)(rectangle, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size()) + Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size())
#endif #endif
); );
image = Image2D{image.storage(), image.format(), image.type(), rectangle.size(), std::move(data)}; image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), rectangle.size(), std::move(data)};
} }
Image2D AbstractFramebuffer::read(const Range2Di& rectangle, Image2D&& image) { Image2D AbstractFramebuffer::read(const Range2Di& rectangle, Image2D&& image) {

72
src/Magnum/GL/AbstractTexture.cpp

@ -1516,7 +1516,7 @@ void AbstractTexture::imageImplementationSvga3DSliceBySlice(const GLenum target,
DSA cleanness is not worth it. */ DSA cleanness is not worth it. */
/** @todo this will break when we support uploading from buffer offset (i.e. data != nullptr) */ /** @todo this will break when we support uploading from buffer offset (i.e. data != nullptr) */
if(target == GL_TEXTURE_1D_ARRAY && data && size.y() > 1) if(target == GL_TEXTURE_1D_ARRAY && data && size.y() > 1)
subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage2DImplementationDefault>(level, {0, 1}, {size.x(), size.y() - 1}, format, type, static_cast<const char*>(data) + std::get<1>(storage.dataProperties(format, type, {size, 1})).x(), storage); subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage2DImplementationDefault>(level, {0, 1}, {size.x(), size.y() - 1}, format, type, static_cast<const char*>(data) + std::get<1>(storage.dataProperties(pixelSize(format, type), {size, 1})).x(), storage);
} }
#endif #endif
@ -1531,7 +1531,7 @@ template<void(AbstractTexture::*original)(GLint, const Vector2i&, const Vector2i
/* Upload the data slice by slice only if this is an array texture and we /* Upload the data slice by slice only if this is an array texture and we
are copying from user memory (not from a buffer) */ are copying from user memory (not from a buffer) */
if(_target == GL_TEXTURE_1D_ARRAY && data) { if(_target == GL_TEXTURE_1D_ARRAY && data) {
const std::size_t stride = std::get<1>(storage.dataProperties(format, type, {size, 1})).x(); const std::size_t stride = std::get<1>(storage.dataProperties(pixelSize(format, type), {size, 1})).x();
for(Int i = 0; i != size.y(); ++i) for(Int i = 0; i != size.y(); ++i)
(this->*original)(level, {offset.x(), offset.y() + i}, {size.x(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage); (this->*original)(level, {offset.x(), offset.y() + i}, {size.x(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage);
@ -1599,7 +1599,7 @@ void AbstractTexture::imageImplementationSvga3DSliceBySlice(GLint level, Texture
#endif #endif
) && data && size.z() > 1) ) && data && size.z() > 1)
{ {
subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage3DImplementationDefault>(level, {0, 0, 1}, {size.xy(), size.z() - 1}, format, type, static_cast<const char*>(data) + std::get<1>(storage.dataProperties(format, type, size)).xy().product(), storage); subImageImplementationSvga3DSliceBySlice<&AbstractTexture::subImage3DImplementationDefault>(level, {0, 0, 1}, {size.xy(), size.z() - 1}, format, type, static_cast<const char*>(data) + std::get<1>(storage.dataProperties(pixelSize(format, type), size)).xy().product(), storage);
} }
} }
#endif #endif
@ -1626,7 +1626,7 @@ template<void(AbstractTexture::*original)(GLint, const Vector3i&, const Vector3i
#endif #endif
) )
{ {
const std::size_t stride = std::get<1>(storage.dataProperties(format, type, size)).xy().product(); const std::size_t stride = std::get<1>(storage.dataProperties(pixelSize(format, type), size)).xy().product();
for(Int i = 0; i != size.z(); ++i) for(Int i = 0; i != size.z(); ++i)
(this->*original)(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage); (this->*original)(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage);
@ -1701,8 +1701,8 @@ template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, Image<
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getImageImplementation)(level, image.format(), image.type(), data.size(), data); (this->*Context::current().state().texture->getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data);
image = Image<dimensions>{image.storage(), image.format(), image.type(), size, std::move(data)}; image = Image<dimensions>{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
} }
template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, Image<1>&); template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, Image<1>&);
@ -1805,8 +1805,8 @@ template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint leve
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer->applyPixelStoragePack(image.storage());
glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), data.size(), data); glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), data.size(), data);
image = Image<dimensions>{image.storage(), image.format(), image.type(), size, std::move(data)}; image = Image<dimensions>{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
} }
template void MAGNUM_GL_EXPORT AbstractTexture::subImage<1>(GLint, const Range1Di&, Image<1>&); template void MAGNUM_GL_EXPORT AbstractTexture::subImage<1>(GLint, const Range1Di&, Image<1>&);
@ -1995,7 +1995,7 @@ void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GL
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(image.format()), GLenum(image.type()), image.data()); glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data());
} }
void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView1D& image) { void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView1D& image) {
@ -2022,13 +2022,13 @@ void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const ImageView1D& image) { void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const ImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data()); (texture.*Context::current().state().texture->subImage1DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data());
} }
void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image) { void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); (texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
} }
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) {
@ -2049,7 +2049,7 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data() (texture.*Context::current().state().texture->image2DImplementation)(target, level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2060,13 +2060,9 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTexImage2D(target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -2079,11 +2075,7 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL
void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, CompressedBufferImage2D& image) { void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr);
} }
@ -2094,7 +2086,7 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data() (texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2105,12 +2097,8 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif (texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
(texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -2122,11 +2110,7 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const
void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) { void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif
(texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); (texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()));
} }
#endif #endif
@ -2137,7 +2121,7 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->image3DImplementation)(level, internalFormat, image.size(), image.format(), image.type(), image.data() (texture.*Context::current().state().texture->image3DImplementation)(level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2148,16 +2132,12 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif
texture.bindInternal(); texture.bindInternal();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTexImage3D(texture._target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
#else #else
glCompressedTexImage3DOES(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTexImage3DOES(texture._target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
#endif #endif
} }
#endif #endif
@ -2172,11 +2152,7 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL
void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage3D& image) { void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr);
} }
@ -2188,7 +2164,7 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data() (texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2199,12 +2175,8 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif (texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
(texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
} }
#endif #endif
@ -2217,11 +2189,7 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const
void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) { void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif
(texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); (texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()));
} }
#endif #endif

66
src/Magnum/GL/BufferImage.cpp

@ -30,19 +30,26 @@
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> const data, const BufferUsage usage): _storage{storage}, _format{format}, _type{type}, _size{size}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{data.size()} { template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> const data, const BufferUsage usage): BufferImage{storage, format, type, size, Buffer{Buffer::TargetHint::PixelPack}, data.size()} {
CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= data.size(), "GL::BufferImage::BufferImage(): bad image data size, got" << data.size() << "but expected at least" << Magnum::Implementation::imageDataSize(*this), );
_buffer.setData(data, usage); _buffer.setData(data, usage);
} }
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> const data, const BufferUsage usage): BufferImage{storage, GL::pixelFormat(format), GL::pixelType(format), size, data, usage} {}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, const std::size_t dataSize) noexcept: _storage{storage}, _format{format}, _type{type}, _size{size}, _buffer{std::move(buffer)}, _dataSize{dataSize} { template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, const std::size_t dataSize) noexcept: _storage{storage}, _format{format}, _type{type}, _size{size}, _buffer{std::move(buffer)}, _dataSize{dataSize} {
CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= dataSize, "GL::BufferImage::BufferImage(): bad image data size, got" << dataSize << "but expected at least" << Magnum::Implementation::imageDataSize(*this), ); CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= dataSize, "GL::BufferImage::BufferImage(): bad image data size, got" << dataSize << "but expected at least" << Magnum::Implementation::imageDataSize(*this), );
} }
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, const std::size_t dataSize) noexcept: BufferImage{storage, GL::pixelFormat(format), GL::pixelType(format), size, std::move(buffer), dataSize} {}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type): _storage{storage}, _format{format}, _type{type}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{0} {} template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type): _storage{storage}, _format{format}, _type{type}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{0} {}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(const PixelStorage storage, const Magnum::PixelFormat format): _storage{storage}, _format{GL::pixelFormat(format)}, _type{GL::pixelType(format)}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{0} {}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(NoCreateT) noexcept: _format{PixelFormat::RGBA}, _type{PixelType::UnsignedByte}, _buffer{NoCreate}, _dataSize{} {} template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(NoCreateT) noexcept: _format{PixelFormat::RGBA}, _type{PixelType::UnsignedByte}, _buffer{NoCreate}, _dataSize{} {}
template<UnsignedInt dimensions> UnsignedInt BufferImage<dimensions>::pixelSize() const { return GL::pixelSize(_format, _type); }
template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> const data, const BufferUsage usage) { template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> const data, const BufferUsage usage) {
_storage = storage; _storage = storage;
_format = format; _format = format;
@ -59,56 +66,37 @@ template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const Pix
} }
} }
template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage( template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const PixelStorage storage, const Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> const data, const BufferUsage usage) {
#ifndef MAGNUM_TARGET_GLES setData(storage, GL::pixelFormat(format), GL::pixelType(format), size, data, usage);
const CompressedPixelStorage storage, }
#endif
const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage): template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage): CompressedBufferImage{storage, format, size, Buffer{Buffer::TargetHint::PixelPack}, data.size()} {
#ifndef MAGNUM_TARGET_GLES
_storage{storage},
#endif
_format{format}, _size{size}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{data.size()}
{
_buffer.setData(data, usage); _buffer.setData(data, usage);
} }
template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage( template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(const CompressedPixelStorage storage, const Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage): CompressedBufferImage{storage, compressedPixelFormat(format), size, data, usage} {}
#ifndef MAGNUM_TARGET_GLES
const CompressedPixelStorage storage, template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, const std::size_t dataSize) noexcept: _storage{storage}, _format{format}, _size{size}, _buffer{std::move(buffer)}, _dataSize{dataSize} {}
#endif
const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, const std::size_t dataSize) noexcept: template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(const CompressedPixelStorage storage, const Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, const std::size_t dataSize) noexcept: CompressedBufferImage{storage, compressedPixelFormat(format), size, std::move(buffer), dataSize} {}
#ifndef MAGNUM_TARGET_GLES
_storage{storage}, template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(const CompressedPixelStorage storage): _storage{storage}, _format{}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{} {}
#endif
_format{format}, _size{size}, _buffer{std::move(buffer)}, _dataSize{dataSize} {}
template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(
#ifndef MAGNUM_TARGET_GLES
const CompressedPixelStorage storage
#endif
):
#ifndef MAGNUM_TARGET_GLES
_storage{storage},
#endif
_format{}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{} {}
template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(NoCreateT) noexcept: _format{}, _buffer{NoCreate}, _dataSize{} {} template<UnsignedInt dimensions> CompressedBufferImage<dimensions>::CompressedBufferImage(NoCreateT) noexcept: _format{}, _buffer{NoCreate}, _dataSize{} {}
template<UnsignedInt dimensions> void CompressedBufferImage<dimensions>::setData( template<UnsignedInt dimensions> void CompressedBufferImage<dimensions>::setData(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage) {
#ifndef MAGNUM_TARGET_GLES
const CompressedPixelStorage storage,
#endif
const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage)
{
#ifndef MAGNUM_TARGET_GLES
_storage = storage; _storage = storage;
#endif
_format = format; _format = format;
_size = size; _size = size;
_buffer.setData(data, usage); _buffer.setData(data, usage);
_dataSize = data.size(); _dataSize = data.size();
} }
template<UnsignedInt dimensions> void CompressedBufferImage<dimensions>::setData(const CompressedPixelStorage storage, const Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage) {
setData(storage, compressedPixelFormat(format), size, data, usage);
}
template<UnsignedInt dimensions> Buffer BufferImage<dimensions>::release() { template<UnsignedInt dimensions> Buffer BufferImage<dimensions>::release() {
_size = {}; _size = {};
_dataSize = {}; _dataSize = {};

479
src/Magnum/GL/BufferImage.h

@ -42,10 +42,46 @@ namespace Magnum { namespace GL {
/** /**
@brief Buffer image @brief Buffer image
Stores image data in GPU memory. Interchangeable with @ref Image, Stores multi-dimensional image data in GPU memory together with layout and
@ref ImageView or @ref Trade::ImageData. pixel format description. See @ref Image for the client memory counterpart.
@see @ref BufferImage1D, @ref BufferImage2D, @ref BufferImage3D,
@ref CompressedBufferImage, @ref Buffer This class can act as a drop-in replacement for @ref Image, @ref ImageView and
@ref Trade::ImageData APIs. See also @ref CompressedBufferImage for equivalent
functionality targeted on compressed image formats.
@section GL-BufferImage-usage Basic usage
The image creates a @ref Buffer instance and fills it with passed data, storing
corresponding image size and pixel format properties. Because this is a
GL-centric class, it's common to specify the format using @ref GL::PixelFormat
and @link GL::PixelType @endlink:
@snippet MagnumGL.cpp BufferImage-usage
It's also possible to pass the generic @ref Magnum::PixelFormat to it, however
the @ref format() and @ref type() queries will always return the GL-specific
value. On construction, the image internally calculates pixel size
corresponding to given pixel format using either @ref GL::pixelSize() or
@ref Magnum::pixelSize(). This value is needed to check that the passed data
are large enough and also required by most of image manipulation operations.
Besides creating and owning the buffer, you can also pass existing buffer to
it, for example to use buffer storage and other advanced functionality. The
image will take an ownership of the buffer, you can use @ref Buffer::wrap() to
make a non-owning copy.
@snippet MagnumGL.cpp BufferImage-usage-wrap
It's also possible to create just an image placeholder, storing only the image
properties without data or size. That is useful for example to specify desired
format of image queries in graphics APIs:
@snippet MagnumGL.cpp BufferImage-usage-query
Similarly to @ref ImageView, this class supports extra storage parameters.
See @ref ImageView-usage for more information.
@see @ref BufferImage1D, @ref BufferImage2D, @ref BufferImage3D
@requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0.
@requires_webgl20 Pixel buffer objects are not available in WebGL 1.0. @requires_webgl20 Pixel buffer objects are not available in WebGL 1.0.
*/ */
@ -66,11 +102,62 @@ template<UnsignedInt dimensions> class BufferImage {
*/ */
explicit BufferImage(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage); explicit BufferImage(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage);
/** @overload /**
* Similar to the above, but uses default @ref PixelStorage parameters. * @brief Constructor
* @param format Format of pixel data
* @param type Data type of pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
*
* Equivalent to calling @ref BufferImage(PixelStorage, PixelFormat, PixelType, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage)
* with default-constructed @ref PixelStorage.
*/ */
explicit BufferImage(PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage): BufferImage{{}, format, type, size, data, usage} {} explicit BufferImage(PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage): BufferImage{{}, format, type, size, data, usage} {}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Constructor
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
explicit CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") BufferImage(PixelStorage storage, Magnum::PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage): BufferImage{storage, PixelFormat(UnsignedInt(format)), type, size, data, usage} {}
/**
* @brief Constructor
*
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
explicit CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") BufferImage(Magnum::PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage): BufferImage{PixelFormat(UnsignedInt(format)), type, size, data, usage} {}
#endif
/**
* @brief Constructor
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
*
* Converts @ref Magnum::PixelFormat to GL-specific values using
* @ref pixelFormat() and @ref pixelType() and then calls
* @ref BufferImage(PixelStorage, PixelFormat, PixelType, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage).
*/
explicit BufferImage(PixelStorage storage, Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage);
/**
* @brief Constructor
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
*
* Equivalent to calling @ref BufferImage(PixelStorage, Magnum::PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage)
* with default-constructed @ref PixelStorage.
*/
explicit BufferImage(Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage): BufferImage{{}, format, size, data, usage} {}
/** /**
* @brief Construct from existing buffer * @brief Construct from existing buffer
* @param storage Storage of pixel data * @param storage Storage of pixel data
@ -85,30 +172,118 @@ template<UnsignedInt dimensions> class BufferImage {
*/ */
explicit BufferImage(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept; explicit BufferImage(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept;
/** @overload /**
* Similar to the above, but uses default @ref PixelStorage parameters. * @brief Construct from existing buffer
* @param format Format of pixel data
* @param type Data type of pixel data
* @param size Image size
* @param buffer Buffer
* @param dataSize Buffer data size
*
* Equivalent to calling @ref BufferImage(PixelStorage, PixelFormat, PixelType, const VectorTypeFor<dimensions, Int>&, Buffer&&, std::size_t)
* with default-constructed @ref PixelStorage.
*/ */
explicit BufferImage(PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept: BufferImage{{}, format, type, size, std::move(buffer), dataSize} {} explicit BufferImage(PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept: BufferImage{{}, format, type, size, std::move(buffer), dataSize} {}
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Constructor * @brief Construct from existing buffer
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
explicit CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") BufferImage(PixelStorage storage, Magnum::PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept: BufferImage{storage, PixelFormat(UnsignedInt(format)), type, size, std::move(buffer), dataSize} {}
/**
* @brief Construct from existing buffer
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
explicit CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") BufferImage(Magnum::PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept: BufferImage{PixelFormat(UnsignedInt(format)), type, size, std::move(buffer), dataSize} {}
#endif
/**
* @brief Construct from existing buffer
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param buffer Buffer
* @param dataSize Buffer data size
*
* Converts @ref Magnum::PixelFormat to GL-specific values using
* @ref pixelFormat() and @ref pixelType() and then calls
* @ref BufferImage(PixelStorage, PixelFormat, PixelType, const VectorTypeFor<dimensions, Int>&, Buffer&&, std::size_t).
*/
explicit BufferImage(PixelStorage storage, Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept;
/**
* @brief Construct from existing buffer
* @param format Format of pixel data
* @param size Image size
* @param buffer Buffer
* @param dataSize Buffer data size
*
* Equivalent to calling @ref BufferImage(PixelStorage, Magnum::PixelFormat, const VectorTypeFor<dimensions, Int>&, Buffer&&, std::size_t)
* with default-constructed @ref PixelStorage.
*/
explicit BufferImage(Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept: BufferImage{{}, format, size, std::move(buffer), dataSize} {}
/**
* @brief Construct an image placeholder
* @param storage Storage of pixel data * @param storage Storage of pixel data
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data * @param type Data type of pixel data
* *
* Size is zero and buffer are empty, call @ref setData() to fill the * Size is zero and buffer are empty, call @ref setData() to fill the
* image with data or use @ref Texture::image() "*Texture::image()"/ * image with data.
* @ref Texture::subImage() "*Texture::subImage()"/
* @ref AbstractFramebuffer::read() "*Framebuffer::read()" to fill the
* image with data using @p storage settings.
*/ */
/*implicit*/ BufferImage(PixelStorage storage, PixelFormat format, PixelType type); /*implicit*/ BufferImage(PixelStorage storage, PixelFormat format, PixelType type);
/** @overload /**
* Similar to the above, but uses default @ref PixelStorage parameters. * @brief Construct an image placeholder
* @param format Format of pixel data
* @param type Data type of pixel data
*
* Equivalent to calling @ref BufferImage(PixelStorage, PixelFormat, PixelType)
* with default-constructed @ref PixelStorage.
*/ */
/*implicit*/ BufferImage(PixelFormat format, PixelType type): BufferImage{{}, format, type} {} /*implicit*/ BufferImage(PixelFormat format, PixelType type): BufferImage{{}, format, type} {}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Construct an image placeholder
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
/*implicit*/ CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") BufferImage(PixelStorage storage, Magnum::PixelFormat format, PixelType type): BufferImage{storage, PixelFormat(UnsignedInt(format)), type} {}
/**
* @brief Construct an image placeholder
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
/*implicit*/ CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") BufferImage(Magnum::PixelFormat format, PixelType type): BufferImage{PixelFormat(UnsignedInt(format)), type} {}
#endif
/**
* @brief Construct an image placeholder
* @param storage Storage of pixel data
* @param format Format of pixel data
*
* Converts @ref Magnum::PixelFormat to GL-specific values using
* @ref pixelFormat() and @ref pixelType() and then calls
* @ref BufferImage(PixelStorage, PixelFormat, PixelType).
*/
/*implicit*/ BufferImage(PixelStorage storage, Magnum::PixelFormat format);
/**
* @brief Construct an image placeholder
* @param format Format of pixel data
*
* Equivalent to calling @ref BufferImage(PixelStorage, Magnum::PixelFormat)
* with default-constructed @ref PixelStorage.
*/
/*implicit*/ BufferImage(Magnum::PixelFormat format): BufferImage{{}, format} {}
/** /**
* @brief Construct without creating the underlying OpenGL object * @brief Construct without creating the underlying OpenGL object
* *
@ -149,7 +324,7 @@ template<UnsignedInt dimensions> class BufferImage {
* *
* @see @ref Magnum::pixelSize(), @ref GL::pixelSize() * @see @ref Magnum::pixelSize(), @ref GL::pixelSize()
*/ */
std::size_t pixelSize() const { return PixelStorage::pixelSize(_format, _type); } UnsignedInt pixelSize() const;
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<Dimensions, Int> size() const { return _size; } VectorTypeFor<Dimensions, Int> size() const { return _size; }
@ -196,11 +371,59 @@ template<UnsignedInt dimensions> class BufferImage {
setData({}, format, type, size, data, usage); setData({}, format, type, size, data, usage);
} }
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Set image data
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") void setData(PixelStorage storage, Magnum::PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage) {
setData(storage, PixelFormat(UnsignedInt(format)), type, size, data, usage);
}
/**
* @brief Set image data
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") void setData(Magnum::PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage) {
setData({}, PixelFormat(UnsignedInt(format)), type, size, data, usage);
}
#endif
/**
* @brief Set image data
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
*
* Converts @ref Magnum::PixelFormat to GL-specific values using
* @ref pixelFormat() and @ref pixelType() and then calls
* @ref setData(PixelStorage, PixelFormat, PixelType, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage).
*/
void setData(PixelStorage storage, Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage);
/**
* @brief Set image data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
*
* Equivalent to calling @ref setData(PixelStorage, Magnum::PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage)
* with default-constructed @ref PixelStorage.
*/
void setData(Magnum::PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage) {
setData({}, format, size, data, usage);
}
/** /**
* @brief Release the image buffer * @brief Release the image buffer
* *
* Releases the ownership of the image buffer and resets internal state * Releases the ownership of the data array and resets @ref size() to
* to default. * zero. The state afterwards is equivalent to moved-from state.
* @see @ref buffer() * @see @ref buffer()
*/ */
Buffer release(); Buffer release();
@ -226,10 +449,43 @@ typedef BufferImage<3> BufferImage3D;
/** /**
@brief Compressed buffer image @brief Compressed buffer image
Stores image data in GPU memory. Stores multi-dimensional compressed image data in GPU memory together with
layout and compressed block description. See @ref CompressedImage for the
client memory counterpart.
This class can act as a drop-in replacement for @ref CompressedImage,
@ref CompressedImageView and @ref Trade::ImageData APIs. See also
@ref BufferImage for equivalent functionality targeted on non-compressed image
formats.
@section GL-CompressedBufferImage-usage Basic usage
The image creates a @ref Buffer instance and fills it with passed data, storing
corresponding image size and compression format properties. Because this is a
GL-centric class, it's common to specify the format using
@link GL::CompressedPixelFormat @endlink:
@snippet MagnumGL.cpp CompressedBufferImage-usage
It's also possible to pass the generic @ref Magnum::CompressedPixelFormat to
it, however the @ref format() query will always return the GL-specific value.
Besides creating and owning the buffer, you can also pass existing buffer to
it, for example to use buffer storage and other advanced functionality. The
image will take an ownership of the buffer, you can use @ref Buffer::wrap() to
make a non-owning copy.
@snippet MagnumGL.cpp CompressedBufferImage-usage-wrap
It's also possible to create just an image placeholder, storing only the image
properties without data or size. That is useful for example to specify desired
format of image queries in graphics APIs:
@snippet MagnumGL.cpp CompressedBufferImage-usage-query
Similarly to @ref CompressedImageView, this class supports extra storage
parameters. See @ref CompressedImageView-usage for more information.
See @ref BufferImage for more information. Interchangeable with @ref CompressedImage,
@ref CompressedImageView or @ref Trade::ImageData.
@see @ref CompressedBufferImage1D, @ref CompressedBufferImage2D, @see @ref CompressedBufferImage1D, @ref CompressedBufferImage2D,
@ref CompressedBufferImage3D @ref CompressedBufferImage3D
@requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0.
@ -241,7 +497,6 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
Dimensions = dimensions /**< Image dimension count */ Dimensions = dimensions /**< Image dimension count */
}; };
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Constructor * @brief Constructor
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
@ -251,11 +506,11 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
* @param usage Image buffer usage * @param usage Image buffer usage
* *
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* for non-default compressed pixel storage
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL. * WebGL.
*/ */
explicit CompressedBufferImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage); explicit CompressedBufferImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage);
#endif
/** /**
* @brief Constructor * @brief Constructor
@ -264,57 +519,112 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
* @param data Image data * @param data Image data
* @param usage Image buffer usage * @param usage Image buffer usage
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref CompressedBufferImage(CompressedPixelStorage, Magnum::CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/ */
explicit CompressedBufferImage(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage); explicit CompressedBufferImage(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage): CompressedBufferImage{{}, format, size, data, usage} {}
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Constructor * @brief Constructor
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data * @param format Format of compressed pixel data
* @param size Image size * @param size Image size
* @param buffer Image data * @param data Image data
* @param dataSize Image buffer usage * @param usage Image buffer usage
*
* Converts @ref Magnum::CompressedPixelFormat to a GL-specific value
* using @ref compressedPixelFormat() and and then calls
* @ref CompressedBufferImage(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage).
*/
explicit CompressedBufferImage(CompressedPixelStorage storage, Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage);
/**
* @brief Constructor
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
* *
* Equivalent to calling @ref CompressedBufferImage(CompressedPixelStorage, Magnum::CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage)
* with default-constructed @ref CompressedPixelStorage.
*/
explicit CompressedBufferImage(Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage): CompressedBufferImage{{}, format, size, data, usage} {}
/**
* @brief Constructor
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param buffer Buffer
* @param dataSize Buffer data size
*
* If @p dataSize is @cpp 0 @ce, the buffer is unconditionally
* reallocated on the first call to @ref setData().
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* for non-default compressed pixel storage
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL. * WebGL.
*/ */
explicit CompressedBufferImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept; explicit CompressedBufferImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept;
#endif
/** @overload /**
* Similar the above, but uses default @ref CompressedPixelStorage * @brief Construct from existing buffer
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * @param format Format of compressed pixel data
* @param size Image size
* @param buffer Buffer
* @param dataSize Buffer data size
*
* Equivalent to calling @ref CompressedBufferImage(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Buffer&&, std::size_t)
* with default-constructed @ref CompressedPixelStorage.
*/ */
explicit CompressedBufferImage(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept; explicit CompressedBufferImage(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept: CompressedBufferImage{{}, format, size, std::move(buffer), dataSize} {}
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Constructor * @brief Construct from existing buffer
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param buffer Buffer
* @param dataSize Buffer data size
*
* Converts @ref Magnum::CompressedPixelFormat to a GL-specific value
* using @ref compressedPixelFormat() and and then calls
* @ref CompressedBufferImage(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Buffer&&, std::size_t).
*/
explicit CompressedBufferImage(CompressedPixelStorage storage, Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept;
/**
* @brief Construct from existing buffer
* @param format Format of compressed pixel data
* @param size Image size
* @param buffer Buffer
* @param dataSize Buffer data size
*
* Equivalent to calling @ref CompressedBufferImage(CompressedPixelStorage, Magnum::CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Buffer&&, std::size_t)
* with default-constructed @ref CompressedPixelStorage.
*/
explicit CompressedBufferImage(Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, std::size_t dataSize) noexcept: CompressedBufferImage{{}, format, size, std::move(buffer), dataSize} {}
/**
* @brief Construct an image placeholder
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
* *
* Format is undefined, size is zero and buffer is empty, call * Format is undefined, size is zero and buffer is empty, call
* @ref setData() to fill the image with data or use * @ref setData() to fill the image with data.
* @ref Texture::compressedImage() "*Texture::compressedImage()"/
* @ref Texture::compressedSubImage() "*Texture::compressedSubImage()"
* to fill the image with data using @p storage settings.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* for non-default compressed pixel storage
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL. * WebGL.
*/ */
/*implicit*/ CompressedBufferImage(CompressedPixelStorage storage); /*implicit*/ CompressedBufferImage(CompressedPixelStorage storage);
#endif
/** /**
* @brief Constructor * @brief Construct an image placeholder
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref CompressedBufferImage(CompressedPixelStorage)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/ */
/*implicit*/ CompressedBufferImage(); /*implicit*/ CompressedBufferImage(): CompressedBufferImage{CompressedPixelStorage{}} {}
/** /**
* @brief Construct without creating the underlying OpenGL object * @brief Construct without creating the underlying OpenGL object
@ -338,16 +648,8 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
/** @brief Move assignment */ /** @brief Move assignment */
CompressedBufferImage<dimensions>& operator=(CompressedBufferImage<dimensions>&& other) noexcept; CompressedBufferImage<dimensions>& operator=(CompressedBufferImage<dimensions>&& other) noexcept;
#ifndef MAGNUM_TARGET_GLES /** @brief Storage of compressed pixel data */
/**
* @brief Storage of compressed pixel data
*
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/
CompressedPixelStorage storage() const { return _storage; } CompressedPixelStorage storage() const { return _storage; }
#endif
/** @brief Format of compressed pixel data */ /** @brief Format of compressed pixel data */
CompressedPixelFormat format() const { return _format; } CompressedPixelFormat format() const { return _format; }
@ -355,7 +657,6 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<Dimensions, Int> size() const { return _size; } VectorTypeFor<Dimensions, Int> size() const { return _size; }
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Compressed image data properties * @brief Compressed image data properties
* *
@ -368,7 +669,6 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Magnum::Implementation::compressedImageDataProperties<dimensions>(*this); return Magnum::Implementation::compressedImageDataProperties<dimensions>(*this);
} }
#endif
/** /**
* @brief Image buffer * @brief Image buffer
@ -380,7 +680,6 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
/** @brief Raw data size */ /** @brief Raw data size */
std::size_t dataSize() const { return _dataSize; } std::size_t dataSize() const { return _dataSize; }
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Set image data * @brief Set image data
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
@ -389,15 +688,13 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
* @param data Image data * @param data Image data
* @param usage Image buffer usage * @param usage Image buffer usage
* *
* Updates the image buffer with given data. The data are *not* deleted * Updates the image buffer with given data.
* after filling the buffer.
* @see @ref Buffer::setData() * @see @ref Buffer::setData()
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL. * WebGL.
*/ */
void setData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage); void setData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage);
#endif
/** /**
* @brief Set image data * @brief Set image data
@ -406,24 +703,52 @@ template<UnsignedInt dimensions> class CompressedBufferImage {
* @param data Image data * @param data Image data
* @param usage Image buffer usage * @param usage Image buffer usage
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref setData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/
void setData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage) {
setData({}, format, size, data, usage);
}
/**
* @brief Set image data
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
*
* Converts @ref Magnum::CompressedPixelFormat to a GL-specific value
* using @ref compressedPixelFormat() and and then calls
* @ref setData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage).
*/
void setData(CompressedPixelStorage storage, Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage);
/**
* @brief Set image data
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param usage Image buffer usage
*
* Equivalent to calling @ref setData(CompressedPixelStorage, Magnum::CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>, BufferUsage)
* with default-constructed @ref CompressedPixelStorage.
*/ */
void setData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage); void setData(Magnum::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data, BufferUsage usage) {
setData({}, format, size, data, usage);
}
/** /**
* @brief Release the image buffer * @brief Release the image buffer
* *
* Releases the ownership of the image buffer and resets internal state * Releases the ownership of the data array and resets @ref size() to
* to default. * zero. The state afterwards is equivalent to moved-from state.
* @see @ref buffer() * @see @ref buffer()
*/ */
Buffer release(); Buffer release();
private: private:
#ifndef MAGNUM_TARGET_GLES
CompressedPixelStorage _storage; CompressedPixelStorage _storage;
#endif
CompressedPixelFormat _format; CompressedPixelFormat _format;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
Buffer _buffer; Buffer _buffer;
@ -443,11 +768,7 @@ template<UnsignedInt dimensions> inline BufferImage<dimensions>::BufferImage(Buf
other._size = {}; other._size = {};
} }
template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>::CompressedBufferImage(CompressedBufferImage<dimensions>&& other) noexcept: template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>::CompressedBufferImage(CompressedBufferImage<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _size{std::move(other._size)}, _buffer{std::move(other._buffer)}, _dataSize{std::move(other._dataSize)} {
#ifndef MAGNUM_TARGET_GLES
_storage{std::move(other._storage)},
#endif
_format{std::move(other._format)}, _size{std::move(other._size)}, _buffer{std::move(other._buffer)}, _dataSize{std::move(other._dataSize)} {
other._size = {}; other._size = {};
other._dataSize = {}; other._dataSize = {};
} }
@ -464,9 +785,7 @@ template<UnsignedInt dimensions> inline BufferImage<dimensions>& BufferImage<dim
template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>& CompressedBufferImage<dimensions>::operator=(CompressedBufferImage<dimensions>&& other) noexcept { template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>& CompressedBufferImage<dimensions>::operator=(CompressedBufferImage<dimensions>&& other) noexcept {
using std::swap; using std::swap;
#ifndef MAGNUM_TARGET_GLES
swap(_storage, other._storage); swap(_storage, other._storage);
#endif
swap(_format, other._format); swap(_format, other._format);
swap(_size, other._size); swap(_size, other._size);
swap(_buffer, other._buffer); swap(_buffer, other._buffer);
@ -474,18 +793,6 @@ template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>& Compr
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>::CompressedBufferImage(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage): CompressedBufferImage{{}, format, size, data, usage} {}
template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>::CompressedBufferImage(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Buffer&& buffer, const std::size_t dataSize) noexcept: CompressedBufferImage{{}, format, size, std::move(buffer), dataSize} {}
template<UnsignedInt dimensions> inline CompressedBufferImage<dimensions>::CompressedBufferImage(): CompressedBufferImage{CompressedPixelStorage{}} {}
template<UnsignedInt dimensions> inline void CompressedBufferImage<dimensions>::setData(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data, const BufferUsage usage) {
setData({}, format, size, data, usage);
}
#endif
} }
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED

69
src/Magnum/GL/CMakeLists.txt

@ -34,12 +34,9 @@ set(MagnumGL_SRCS
Context.cpp Context.cpp
DefaultFramebuffer.cpp DefaultFramebuffer.cpp
Framebuffer.cpp Framebuffer.cpp
../Image.cpp # temporary
../ImageView.cpp # temporary
Mesh.cpp Mesh.cpp
MeshView.cpp MeshView.cpp
OpenGL.cpp OpenGL.cpp
PixelFormat.cpp
Renderbuffer.cpp Renderbuffer.cpp
Renderer.cpp Renderer.cpp
Sampler.cpp Sampler.cpp
@ -59,6 +56,9 @@ set(MagnumGL_SRCS
Implementation/driverSpecific.cpp Implementation/driverSpecific.cpp
Implementation/maxTextureSize.cpp) Implementation/maxTextureSize.cpp)
set(MagnumGL_GracefulAssert_SRCS
PixelFormat.cpp)
set(MagnumGL_HEADERS set(MagnumGL_HEADERS
AbstractFramebuffer.h AbstractFramebuffer.h
AbstractObject.h AbstractObject.h
@ -170,16 +170,35 @@ if(NOT (TARGET_WEBGL AND TARGET_GLES2))
Implementation/QueryState.h) Implementation/QueryState.h)
endif() endif()
# Objects shared between main and test library
add_library(MagnumGLObjects OBJECT
${MagnumGL_SRCS}
${MagnumGL_HEADERS}
${MagnumGL_PRIVATE_HEADERS})
# We can use both implicit include path (GLES2/gl2.h) where our headers can
# be overriden with system ones or explicit (MagnumExternal/OpenGL/GLES2/gl2ext.h)
# where only our headers will be used
target_include_directories(MagnumGLObjects PUBLIC
$<TARGET_PROPERTY:Magnum,INTERFACE_INCLUDE_DIRECTORIES>
${PROJECT_SOURCE_DIR}/src/MagnumExternal/OpenGL)
if(NOT BUILD_STATIC)
target_compile_definitions(MagnumGLObjects PRIVATE "MagnumGLObjects_EXPORTS" "FlextGL_EXPORTS")
endif()
if(NOT BUILD_STATIC OR BUILD_STATIC_PIC)
set_target_properties(MagnumGLObjects PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
set_target_properties(MagnumGLObjects PROPERTIES FOLDER "Magnum/GL")
# Link in GL function pointer variables on platforms that support it # Link in GL function pointer variables on platforms that support it
if(NOT CORRADE_TARGET_EMSCRIPTEN) if(NOT CORRADE_TARGET_EMSCRIPTEN)
list(APPEND MagnumGL_SRCS $<TARGET_OBJECTS:MagnumFlextGLObjects>) set(MagnumGL_FlextGL_SRCS $<TARGET_OBJECTS:MagnumFlextGLObjects>)
endif() endif()
# GL library # GL library
add_library(MagnumGL ${SHARED_OR_STATIC} add_library(MagnumGL ${SHARED_OR_STATIC}
${MagnumGL_SRCS} $<TARGET_OBJECTS:MagnumGLObjects>
${MagnumGL_HEADERS} ${MagnumGL_FlextGL_SRCS}
${MagnumGL_PRIVATE_HEADERS}) ${MagnumGL_GracefulAssert_SRCS})
set_target_properties(MagnumGL PROPERTIES set_target_properties(MagnumGL PROPERTIES
DEBUG_POSTFIX "-d" DEBUG_POSTFIX "-d"
FOLDER "Magnum/GL") FOLDER "Magnum/GL")
@ -193,8 +212,6 @@ endif()
# be overriden with system ones or explicit (MagnumExternal/OpenGL/GLES2/gl2ext.h) # be overriden with system ones or explicit (MagnumExternal/OpenGL/GLES2/gl2ext.h)
# where only our headers will be used # where only our headers will be used
target_include_directories(MagnumGL PUBLIC target_include_directories(MagnumGL PUBLIC
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src
${PROJECT_SOURCE_DIR}/src/MagnumExternal/OpenGL) ${PROJECT_SOURCE_DIR}/src/MagnumExternal/OpenGL)
target_link_libraries(MagnumGL PUBLIC Magnum) target_link_libraries(MagnumGL PUBLIC Magnum)
if(NOT TARGET_GLES OR TARGET_DESKTOP_GLES) if(NOT TARGET_GLES OR TARGET_DESKTOP_GLES)
@ -249,6 +266,40 @@ if(WITH_OPENGLTESTER)
endif() endif()
if(BUILD_TESTS) if(BUILD_TESTS)
# Library with graceful assert for testing
add_library(MagnumGLTestLib ${SHARED_OR_STATIC}
$<TARGET_OBJECTS:MagnumGLObjects>
${MagnumGL_FlextGL_SRCS}
${MagnumGL_GracefulAssert_SRCS})
target_include_directories(MagnumGLTestLib PUBLIC
${PROJECT_SOURCE_DIR}/src/MagnumExternal/OpenGL)
set_target_properties(MagnumGLTestLib PROPERTIES
DEBUG_POSTFIX "-d"
FOLDER "Magnum/GL")
target_compile_definitions(MagnumGLTestLib PRIVATE
"CORRADE_GRACEFUL_ASSERT" "MagnumGL_EXPORTS" "FlextGL_EXPORTS")
if(BUILD_STATIC_PIC)
set_target_properties(MagnumGLTestLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
target_link_libraries(MagnumGLTestLib PUBLIC
Magnum)
if(NOT TARGET_GLES OR TARGET_DESKTOP_GLES)
target_link_libraries(MagnumGLTestLib PUBLIC ${OPENGL_gl_LIBRARY})
elseif(TARGET_GLES2)
target_link_libraries(MagnumGLTestLib PUBLIC OpenGLES2::OpenGLES2)
else()
target_link_libraries(MagnumGLTestLib PUBLIC OpenGLES3::OpenGLES3)
endif()
# On Windows we need to install first and then run the tests to avoid "DLL
# not found" hell, thus we need to install this too
if(CORRADE_TARGET_WINDOWS AND NOT CMAKE_CROSSCOMPILING AND NOT BUILD_STATIC)
install(TARGETS MagnumGLTestLib
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
add_subdirectory(Test) add_subdirectory(Test)
endif() endif()

27
src/Magnum/GL/CubeMapTexture.cpp

@ -30,6 +30,7 @@
#include "Magnum/GL/BufferImage.h" #include "Magnum/GL/BufferImage.h"
#endif #endif
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/GL/PixelFormat.h"
#include "Magnum/GL/Implementation/maxTextureSize.h" #include "Magnum/GL/Implementation/maxTextureSize.h"
#include "Magnum/GL/Implementation/RendererState.h" #include "Magnum/GL/Implementation/RendererState.h"
#include "Magnum/GL/Implementation/State.h" #include "Magnum/GL/Implementation/State.h"
@ -74,8 +75,8 @@ void CubeMapTexture::image(const Int level, Image3D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer->applyPixelStoragePack(image.storage());
glGetTextureImage(_id, level, GLenum(image.format()), GLenum(image.type()), data.size(), data); glGetTextureImage(_id, level, GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), data.size(), data);
image = Image3D{image.storage(), image.format(), image.type(), size, std::move(data)}; image = Image3D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
} }
Image3D CubeMapTexture::image(const Int level, Image3D&& image) { Image3D CubeMapTexture::image(const Int level, Image3D&& image) {
@ -182,8 +183,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level,
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), data.size(), data); (this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data);
image = Image2D{image.storage(), image.format(), image.type(), size, std::move(data)}; image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
} }
Image2D CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, Image2D&& image) { Image2D CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, Image2D&& image) {
@ -298,7 +299,7 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data(), image.storage()); (this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data(), image.storage());
return *this; return *this;
} }
@ -316,7 +317,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vec
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(compressedPixelFormat(image.format())), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
return *this; return *this;
} }
@ -335,7 +336,7 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate,
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), image.data() (this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -356,23 +357,15 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate co
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif (this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
(this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, CompressedBufferImage2D& image) { CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
#ifndef MAGNUM_TARGET_GLES
/* Pixel storage is completely ignored for compressed images on ES, no need
to reset anything */
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
#endif
(this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); (this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()));
return *this; return *this;
} }
@ -509,7 +502,7 @@ void CubeMapTexture::subImageImplementationDefault(const GLint level, const Vect
} }
void CubeMapTexture::subImageImplementationSvga3DSliceBySlice(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage& storage) { void CubeMapTexture::subImageImplementationSvga3DSliceBySlice(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage& storage) {
const std::size_t stride = std::get<1>(storage.dataProperties(format, type, size)).xy().product(); const std::size_t stride = std::get<1>(storage.dataProperties(pixelSize(format, type), size)).xy().product();
for(Int i = 0; i != size.z(); ++i) for(Int i = 0; i != size.z(); ++i)
subImageImplementationDefault(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage); subImageImplementationDefault(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage);
} }

6
src/Magnum/GL/Implementation/RendererState.cpp

@ -194,6 +194,11 @@ void RendererState::applyPixelStorageUnpack(const Magnum::PixelStorage& storage)
} }
void RendererState::applyPixelStorageInternal(const CompressedPixelStorage& storage, const bool isUnpack) { void RendererState::applyPixelStorageInternal(const CompressedPixelStorage& storage, const bool isUnpack) {
#ifdef MAGNUM_TARGET_GLES
CORRADE_ASSERT(storage == CompressedPixelStorage{},
"GL: non-default CompressedPixelStorage parameters are not supported on OpenGLES or WebGL", );
static_cast<void>(isUnpack);
#else
applyPixelStorageInternal(static_cast<const Magnum::PixelStorage&>(storage), isUnpack); applyPixelStorageInternal(static_cast<const Magnum::PixelStorage&>(storage), isUnpack);
PixelStorage& state = isUnpack ? unpackPixelStorage : packPixelStorage; PixelStorage& state = isUnpack ? unpackPixelStorage : packPixelStorage;
@ -221,6 +226,7 @@ void RendererState::applyPixelStorageInternal(const CompressedPixelStorage& stor
state.compressedBlockDataSize != storage.compressedBlockDataSize()) state.compressedBlockDataSize != storage.compressedBlockDataSize())
glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_SIZE : GL_PACK_COMPRESSED_BLOCK_SIZE, glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_SIZE : GL_PACK_COMPRESSED_BLOCK_SIZE,
state.compressedBlockDataSize = storage.compressedBlockDataSize()); state.compressedBlockDataSize = storage.compressedBlockDataSize());
#endif
} }
}}} }}}

32
src/Magnum/GL/Implementation/compressedPixelFormatMapping.hpp

@ -0,0 +1,32 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* See Magnum/GL/PixelFormat.cpp and Magnum/GL/Test/PixelFormatTest.cpp */
#ifdef _c
_c(Bc1RGBUnorm, RGBS3tcDxt1)
_c(Bc1RGBAUnorm, RGBAS3tcDxt1)
_c(Bc2RGBAUnorm, RGBAS3tcDxt3)
_c(Bc3RGBAUnorm, RGBAS3tcDxt5)
#endif

140
src/Magnum/GL/Implementation/pixelFormatMapping.hpp

@ -0,0 +1,140 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* See Magnum/GL/PixelFormat.cpp and Magnum/GL/Test/PixelFormatTest.cpp */
#ifdef _c
#ifndef MAGNUM_TARGET_GLES2
_c(R8Unorm, Red, UnsignedByte)
_c(RG8Unorm, RG, UnsignedByte)
#else
_c(R8Unorm, Luminance, UnsignedByte)
_c(RG8Unorm, LuminanceAlpha, UnsignedByte)
#endif
_c(RGB8Unorm, RGB, UnsignedByte)
_c(RGBA8Unorm, RGBA, UnsignedByte)
#ifndef MAGNUM_TARGET_GLES2
_c(R8Snorm, Red, Byte)
_c(RG8Snorm, RG, Byte)
_c(RGB8Snorm, RGB, Byte)
_c(RGBA8Snorm, RGBA, Byte)
#else
_s(R8Snorm)
_s(RG8Snorm)
_s(RGB8Snorm)
_s(RGBA8Snorm)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(R8UI, RedInteger, UnsignedByte)
_c(RG8UI, RGInteger, UnsignedByte)
_c(RGB8UI, RGBInteger, UnsignedByte)
_c(RGBA8UI, RGBAInteger, UnsignedByte)
_c(R8I, RedInteger, Byte)
_c(RG8I, RGInteger, Byte)
_c(RGB8I, RGBInteger, Byte)
_c(RGBA8I, RGBAInteger, Byte)
#else
_s(R8UI)
_s(RG8UI)
_s(RGB8UI)
_s(RGBA8UI)
_s(R8I)
_s(RG8I)
_s(RGB8I)
_s(RGBA8I)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(R16Unorm, Red, UnsignedShort)
_c(RG16Unorm, RG, UnsignedShort)
#else
_c(R16Unorm, Luminance, UnsignedShort)
_c(RG16Unorm, LuminanceAlpha, UnsignedShort)
#endif
_c(RGB16Unorm, RGB, UnsignedShort)
_c(RGBA16Unorm, RGBA, UnsignedShort)
#ifndef MAGNUM_TARGET_GLES2
_c(R16Snorm, Red, Short)
_c(RG16Snorm, RG, Short)
_c(RGB16Snorm, RGB, Short)
_c(RGBA16Snorm, RGBA, Short)
#else
_s(R16Snorm)
_s(RG16Snorm)
_s(RGB16Snorm)
_s(RGBA16Snorm)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(R16UI, RedInteger, UnsignedShort)
_c(RG16UI, RGInteger, UnsignedShort)
_c(RGB16UI, RGBInteger, UnsignedShort)
_c(RGBA16UI, RGBAInteger, UnsignedShort)
_c(R16I, RedInteger, Short)
_c(RG16I, RGInteger, Short)
_c(RGB16I, RGBInteger, Short)
_c(RGBA16I, RGBAInteger, Short)
_c(R32UI, RedInteger, UnsignedInt)
_c(RG32UI, RGInteger, UnsignedInt)
_c(RGB32UI, RGBInteger, UnsignedInt)
_c(RGBA32UI, RGBAInteger, UnsignedInt)
_c(R32I, RedInteger, Int)
_c(RG32I, RGInteger, Int)
_c(RGB32I, RGBInteger, Int)
_c(RGBA32I, RGBAInteger, Int)
#else
_s(R16UI)
_s(RG16UI)
_s(RGB16UI)
_s(RGBA16UI)
_s(R16I)
_s(RG16I)
_s(RGB16I)
_s(RGBA16I)
_s(R32UI)
_s(RG32UI)
_s(RGB32UI)
_s(RGBA32UI)
_s(R32I)
_s(RG32I)
_s(RGB32I)
_s(RGBA32I)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(R16F, Red, HalfFloat)
_c(RG16F, RG, HalfFloat)
#else
_c(R16F, Luminance, HalfFloat)
_c(RG16F, LuminanceAlpha, HalfFloat)
#endif
_c(RGB16F, RGB, HalfFloat)
_c(RGBA16F, RGBA, HalfFloat)
#ifndef MAGNUM_TARGET_GLES2
_c(R32F, Red, Float)
_c(RG32F, RG, Float)
#else
_c(R32F, Luminance, Float)
_c(RG32F, LuminanceAlpha, Float)
#endif
_c(RGB32F, RGB, Float)
_c(RGBA32F, RGBA, Float)
#endif

126
src/Magnum/GL/PixelFormat.cpp

@ -26,11 +26,85 @@
#include "PixelFormat.h" #include "PixelFormat.h"
#include <Corrade/Utility/Assert.h> #include <Corrade/Utility/Assert.h>
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
#include "Magnum/PixelFormat.h"
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
std::size_t pixelSize(const PixelFormat format, const PixelType type) { namespace {
#ifndef DOXYGEN_GENERATING_OUTPUT /* It gets *really* confused */
constexpr struct {
PixelFormat format;
PixelType type;
} FormatMapping[] {
#define _c(input, format, type) {PixelFormat::format, PixelType::type},
#define _s(input) {PixelFormat{}, PixelType{}},
#include "Magnum/GL/Implementation/pixelFormatMapping.hpp"
#undef _s
#undef _c
};
#endif
}
bool hasPixelFormat(const Magnum::PixelFormat format) {
if(isPixelFormatImplementationSpecific(format))
return true;
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/* See GL/Test/PixelFormatTest.cpp for more information. Returning true
unconditionally here as unsupported enum values shouldn't even be
compiled. */
if(UnsignedInt(format) > 0x1000) return true;
#endif
CORRADE_ASSERT(UnsignedInt(format) < Containers::arraySize(FormatMapping),
"GL::hasPixelFormat(): invalid format" << format, {});
return UnsignedInt(FormatMapping[UnsignedInt(format)].format);
}
PixelFormat pixelFormat(const Magnum::PixelFormat format) {
if(isPixelFormatImplementationSpecific(format))
return pixelFormatUnwrap<GL::PixelFormat>(format);
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/* See GL/Test/PixelFormatTest.cpp for more information */
if(UnsignedInt(format) > 0x1000)
return PixelFormat(UnsignedInt(format));
#endif
CORRADE_ASSERT(UnsignedInt(format) < Containers::arraySize(FormatMapping),
"GL::pixelFormat(): invalid format" << format, {});
const PixelFormat out = FormatMapping[UnsignedInt(format)].format;
CORRADE_ASSERT(UnsignedInt(out),
"GL::pixelFormat(): format" << format << "is not supported on this target", {});
return out;
}
PixelType pixelType(const Magnum::PixelFormat format, const UnsignedInt extra) {
if(isPixelFormatImplementationSpecific(format)
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/* See GL/Test/PixelFormatTest.cpp for more information */
|| UnsignedInt(format) > 0x1000
#endif
) {
CORRADE_ASSERT(extra,
"GL::pixelType(): format is implementation-specific, but no additional type specifier was passed", {});
return PixelType(extra);
}
CORRADE_ASSERT(UnsignedInt(format) < Containers::arraySize(FormatMapping),
"GL::pixelType(): invalid format" << format, {});
const PixelType out = FormatMapping[UnsignedInt(format)].type;
CORRADE_ASSERT(UnsignedInt(out),
"GL::pixelType(): format" << format << "is not supported on this target", {});
return out;
}
UnsignedInt pixelSize(const PixelFormat format, const PixelType type) {
std::size_t size = 0; std::size_t size = 0;
switch(type) { switch(type) {
case PixelType::UnsignedByte: case PixelType::UnsignedByte:
@ -149,7 +223,7 @@ std::size_t pixelSize(const PixelFormat format, const PixelType type) {
/* Handled above */ /* Handled above */
case PixelFormat::DepthStencil: case PixelFormat::DepthStencil:
CORRADE_ASSERT(false, "GL::pixelSize(): invalid GL::PixelType specified for depth/stencil GL::PixelFormat", 0); CORRADE_ASSERT(false, "GL::pixelSize(): invalid" << type << "specified for" << format, 0);
} }
CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
@ -271,6 +345,54 @@ Debug& operator<<(Debug& debug, const PixelType value) {
return debug << "GL::PixelType(" << Debug::nospace << reinterpret_cast<void*>(GLenum(value)) << Debug::nospace << ")"; return debug << "GL::PixelType(" << Debug::nospace << reinterpret_cast<void*>(GLenum(value)) << Debug::nospace << ")";
} }
namespace {
#ifndef DOXYGEN_GENERATING_OUTPUT /* It gets *really* confused */
constexpr CompressedPixelFormat CompressedFormatMapping[] {
#define _c(input, format) GL::CompressedPixelFormat::format,
#define _s(input) GL::CompressedPixelFormat{},
#include "Magnum/GL/Implementation/compressedPixelFormatMapping.hpp"
#undef _s
#undef _c
};
#endif
}
bool hasCompressedPixelFormat(const Magnum::CompressedPixelFormat format) {
if(isCompressedPixelFormatImplementationSpecific(format))
return true;
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/* See GL/Test/PixelFormatTest.cpp for more information. Returning true
unconditionally here as unsupported enum values shouldn't even be
compiled. */
if(UnsignedInt(format) > 0x1000) return true;
#endif
CORRADE_ASSERT(UnsignedInt(format) < Containers::arraySize(CompressedFormatMapping),
"GL::hasCompressedPixelFormat(): invalid format" << format, {});
return UnsignedInt(CompressedFormatMapping[UnsignedInt(format)]);
}
CompressedPixelFormat compressedPixelFormat(const Magnum::CompressedPixelFormat format) {
if(isCompressedPixelFormatImplementationSpecific(format))
return compressedPixelFormatUnwrap<GL::CompressedPixelFormat>(format);
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/* See GL/Test/PixelFormatTest.cpp for more information */
if(UnsignedInt(format) > 0x1000)
return CompressedPixelFormat(UnsignedInt(format));
#endif
CORRADE_ASSERT(UnsignedInt(format) < Containers::arraySize(CompressedFormatMapping),
"GL::compressedPixelFormat(): invalid format" << format, {});
const CompressedPixelFormat out = CompressedFormatMapping[UnsignedInt(format)];
CORRADE_ASSERT(UnsignedInt(out),
"GL::compressedPixelFormat(): format" << format << "is not supported on this target", {});
return out;
}
Debug& operator<<(Debug& debug, const CompressedPixelFormat value) { Debug& operator<<(Debug& debug, const CompressedPixelFormat value) {
switch(value) { switch(value) {
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */

142
src/Magnum/GL/PixelFormat.h

@ -26,9 +26,11 @@
*/ */
/** @file /** @file
* @brief Enum @ref Magnum::GL::PixelFormat, @ref Magnum::GL::PixelType, @ref Magnum::GL::CompressedPixelFormat, function @ref Magnum::GL::pixelSize() * @brief Enum @ref Magnum::GL::PixelFormat, @ref Magnum::GL::PixelType, @ref Magnum::GL::CompressedPixelFormat, function @ref Magnum::GL::hasPixelFormat(), @ref Magnum::GL::pixelFormat(), @ref Magnum::GL::pixelType(), @ref Magnum::GL::pixelSize(), @ref Magnum::GL::hasCompressedPixelFormat(), @ref Magnum::GL::compressedPixelFormat()
*/ */
#include <Corrade/Utility/Assert.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/OpenGL.h"
#include "Magnum/GL/visibility.h" #include "Magnum/GL/visibility.h"
@ -50,7 +52,8 @@ In most cases you may want to use @ref PixelFormat::Red (for grayscale images),
See documentation of these values for possible limitations when using OpenGL ES See documentation of these values for possible limitations when using OpenGL ES
2.0 or WebGL. 2.0 or WebGL.
@see @ref Image, @ref ImageView, @ref BufferImage, @ref Trade::ImageData @see @ref Magnum::PixelFormat, @ref pixelFormat(), @ref hasPixelFormat(),
@ref Image, @ref ImageView, @ref BufferImage, @ref Trade::ImageData
@m_enum_values_as_keywords @m_enum_values_as_keywords
*/ */
enum class PixelFormat: GLenum { enum class PixelFormat: GLenum {
@ -333,7 +336,8 @@ In most cases you may want to use @ref PixelType::UnsignedByte along with
See documentation of these values for possible limitations when using OpenGL ES See documentation of these values for possible limitations when using OpenGL ES
2.0 or WebGL. 2.0 or WebGL.
@see @ref Image, @ref ImageView, @ref BufferImage, @ref Trade::ImageData @see @ref Magnum::PixelFormat, @ref pixelType(), @ref hasPixelFormat(),
@ref Image, @ref ImageView, @ref BufferImage, @ref Trade::ImageData
@m_enum_values_as_keywords @m_enum_values_as_keywords
*/ */
enum class PixelType: GLenum { enum class PixelType: GLenum {
@ -595,13 +599,94 @@ enum class PixelType: GLenum {
#endif #endif
}; };
/**
@brief Check availability of a generic pixel format
Some OpenGL targets don't support all generic pixel formats (for example WebGL
1.0 and OpenGL ES 2.0 don't support most of single- and two-component or
integer formats). Returns @cpp false @ce if current target can't support such
format, @cpp true @ce otherwise. Moreover, returns @cpp true @ce also for all
formats that are @ref isPixelFormatImplementationSpecific(). The @p format
value is expected to be valid.
@note Support of some formats depends on presence of a particular OpenGL
extension. Such check is outside of the scope of this function and you are
expected to verify extension availability before using such format.
@see @ref pixelFormat(), @ref pixelType()
*/
MAGNUM_GL_EXPORT bool hasPixelFormat(Magnum::PixelFormat format);
/**
@brief Convert a generic pixel format to OpenGL pixel format
In case @ref isPixelFormatImplementationSpecific() returns @cpp false @ce for
@p format, maps it to a corresponding OpenGL pixel format. In case
@ref isPixelFormatImplementationSpecific() returns @cpp true @ce, assumes
@p format stores OpenGL-specific pixel format and returns
@ref pixelFormatUnwrap() cast to @ref GL::PixelFormat.
Not all generic pixel formats may be available on all targets and this function
expects that given format is available on the target. Use @ref hasPixelFormat()
to query availability of given format.
@note On OpenGL ES 2.0 and WebGL 1.0, one- and two-channel texture formats are
always translated to @ref PixelFormat::Luminance and
@ref PixelFormat::LuminanceAlpha, independently on the
@extension{EXT,texture_rg} being present or not. If you wish to use @ref PixelFormat::Red and @ref PixelFormat::RG instead, specify the GL-specific
pixel format directly instead of using the generic enum.
@see @ref pixelType()
*/
MAGNUM_GL_EXPORT PixelFormat pixelFormat(Magnum::PixelFormat format);
/**
@brief Convert a generic pixel type to OpenGL pixel type
In case @ref isPixelFormatImplementationSpecific() returns @cpp false @ce for
@p format, maps it to a corresponding OpenGL pixel type. In case
@ref isPixelFormatImplementationSpecific() returns @cpp true @ce, assumes
@p extra stores OpenGL-specific pixel type and returns it cast to
@ref GL::PixelType.
Not all generic pixel formats may be available on all targets and this function
expects that given format is available on the target. Use @ref hasPixelFormat()
to query availability of given format.
@see @ref pixelFormat()
*/
MAGNUM_GL_EXPORT PixelType pixelType(Magnum::PixelFormat format, UnsignedInt extra = 0);
/**
@brief Pixel size for given format/type combination (in bytes)
@see @ref Magnum::pixelSize(), @ref PixelStorage::dataProperties()
*/
MAGNUM_GL_EXPORT UnsignedInt pixelSize(PixelFormat format, PixelType type);
#ifdef MAGNUM_BUILD_DEPRECATED
/** @brief @copybrief pixelSize(PixelFormat, PixelType)
* @deprecated Use either @ref GL::PixelFormat together with
* @ref GL::PixelType or just @ref Magnum::PixelFormat instead
*/
inline CORRADE_DEPRECATED("use either GL::PixelFormat together with GL::PixelType or just Magnum::PixelFormat instead") UnsignedInt pixelSize(Magnum::PixelFormat format, PixelType type) {
return pixelSize(PixelFormat(UnsignedInt(format)), type);
}
#endif
/** @debugoperatorenum{PixelFormat} */
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, PixelFormat value);
/** @debugoperatorenum{PixelType} */
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, PixelType value);
/** /**
@brief Format of compressed pixel data @brief Format of compressed pixel data
Equivalent to `Compressed*` values of @ref TextureFormat enum. Equivalent to `Compressed*` values of @ref TextureFormat enum.
@see @ref CompressedImage, @ref CompressedImageView, @ref CompressedBufferImage, @see @ref Magnum::CompressedPixelFormat, @ref compressedPixelFormat(),
@ref Trade::ImageData @ref hasCompressedPixelFormat(), @ref CompressedImage,
@ref CompressedImageView, @ref CompressedBufferImage, @ref Trade::ImageData
@m_enum_values_as_keywords @m_enum_values_as_keywords
*/ */
enum class CompressedPixelFormat: GLenum { enum class CompressedPixelFormat: GLenum {
@ -1235,17 +1320,38 @@ enum class CompressedPixelFormat: GLenum {
}; };
/** /**
@brief Pixel size for given format/type combination (in bytes) @brief Check availability of generic compressed pixel format
@see @ref PixelStorage::dataProperties() Some OpenGL targets don't support all generic pixel formats (for example ASTC
*/ compression might not be available on WebGL 1.0). Returns @cpp false @ce if
MAGNUM_GL_EXPORT std::size_t pixelSize(PixelFormat format, PixelType type); current target can't support such format, @cpp true @ce otherwise. Moreover,
returns @cpp true @ce also for all formats that are
@ref isCompressedPixelFormatImplementationSpecific().The @p format value is
expected to be valid.
/** @debugoperatorenum{PixelFormat} */ @note Support of some formats depends on presence of a particular OpenGL
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, PixelFormat value); extension. Such check is outside of the scope of this function and you are
expected to verify extension availability before using such format.
/** @debugoperatorenum{PixelType} */ @see @ref pixelFormat(), @ref pixelType()
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, PixelType value); */
MAGNUM_GL_EXPORT bool hasCompressedPixelFormat(Magnum::CompressedPixelFormat format);
/**
@brief Convert generic compressed pixel format to OpenGL compressed pixel format
In case @ref isCompressedPixelFormatImplementationSpecific() returns
@cpp false @ce for @p format, maps it to a corresponding OpenGL pixel format.
In case @ref isCompressedPixelFormatImplementationSpecific() returns
@cpp true @ce, assumes @p format stores OpenGL-specific pixel format and
returns @ref compressedPixelFormatUnwrap() cast to @ref GL::CompressedPixelFormat.
Not all generic pixel formats may be available on all targets and this function
expects that given format is available on the target. Use
@ref hasCompressedPixelFormat() to query availability of given format.
@see @ref pixelFormat()
*/
MAGNUM_GL_EXPORT CompressedPixelFormat compressedPixelFormat(Magnum::CompressedPixelFormat format);
/** @debugoperatorenum{CompressedPixelFormat} */ /** @debugoperatorenum{CompressedPixelFormat} */
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, CompressedPixelFormat value); MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, CompressedPixelFormat value);
@ -1255,20 +1361,10 @@ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, CompressedPixelFormat value);
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/* Note: needs to be prefixed with Magnum:: otherwise Doxygen can't find it */ /* Note: needs to be prefixed with Magnum:: otherwise Doxygen can't find it */
/** @brief @copybrief GL::PixelFormat
* @deprecated Use @ref GL::PixelFormat instead.
*/
typedef CORRADE_DEPRECATED("use GL::PixelFormat instead") Magnum::GL::PixelFormat PixelFormat;
/** @brief @copybrief GL::PixelType /** @brief @copybrief GL::PixelType
* @deprecated Use @ref GL::PixelType instead. * @deprecated Use @ref GL::PixelType instead.
*/ */
typedef CORRADE_DEPRECATED("use GL::PixelType instead") Magnum::GL::PixelType PixelType; typedef CORRADE_DEPRECATED("use GL::PixelType instead") Magnum::GL::PixelType PixelType;
/** @brief @copybrief GL::CompressedPixelFormat
* @deprecated Use @ref GL::CompressedPixelFormat instead.
*/
typedef CORRADE_DEPRECATED("use GL::CompressedPixelFormat instead") Magnum::GL::CompressedPixelFormat CompressedPixelFormat;
#endif #endif
} }

20
src/Magnum/GL/Test/BufferImageGLTest.cpp

@ -80,7 +80,7 @@ void BufferImageGLTest::construct() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(a.storage().alignment(), 1); CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::Red); CORRADE_COMPARE(a.format(), GL::PixelFormat::Red);
CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); CORRADE_COMPARE(a.type(), PixelType::UnsignedByte);
CORRADE_COMPARE(a.size(), Vector2i(1, 3)); CORRADE_COMPARE(a.size(), Vector2i(1, 3));
@ -109,7 +109,7 @@ void BufferImageGLTest::constructCompressed() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
#endif #endif
CORRADE_COMPARE(a.format(), CompressedPixelFormat::RGBAS3tcDxt1); CORRADE_COMPARE(a.format(), GL::CompressedPixelFormat::RGBAS3tcDxt1);
CORRADE_COMPARE(a.size(), Vector2i(4, 4)); CORRADE_COMPARE(a.size(), Vector2i(4, 4));
CORRADE_COMPARE(a.dataSize(), 8); CORRADE_COMPARE(a.dataSize(), 8);
@ -138,7 +138,7 @@ void BufferImageGLTest::constructBuffer() {
CORRADE_VERIFY(!buffer.id()); CORRADE_VERIFY(!buffer.id());
CORRADE_COMPARE(a.buffer().id(), id); CORRADE_COMPARE(a.buffer().id(), id);
CORRADE_COMPARE(a.storage().alignment(), 1); CORRADE_COMPARE(a.storage().alignment(), 1);
CORRADE_COMPARE(a.format(), PixelFormat::Red); CORRADE_COMPARE(a.format(), GL::PixelFormat::Red);
CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); CORRADE_COMPARE(a.type(), PixelType::UnsignedByte);
CORRADE_COMPARE(a.size(), Vector2i(1, 3)); CORRADE_COMPARE(a.size(), Vector2i(1, 3));
@ -173,7 +173,7 @@ void BufferImageGLTest::constructBufferCompressed() {
#endif #endif
CORRADE_VERIFY(!buffer.id()); CORRADE_VERIFY(!buffer.id());
CORRADE_COMPARE(a.buffer().id(), id); CORRADE_COMPARE(a.buffer().id(), id);
CORRADE_COMPARE(a.format(), CompressedPixelFormat::RGBAS3tcDxt1); CORRADE_COMPARE(a.format(), GL::CompressedPixelFormat::RGBAS3tcDxt1);
CORRADE_COMPARE(a.size(), Vector2i(4, 4)); CORRADE_COMPARE(a.size(), Vector2i(4, 4));
CORRADE_COMPARE(a.dataSize(), 8); CORRADE_COMPARE(a.dataSize(), 8);
@ -208,7 +208,7 @@ void BufferImageGLTest::constructMove() {
CORRADE_COMPARE(a.size(), Vector2i()); CORRADE_COMPARE(a.size(), Vector2i());
CORRADE_COMPARE(b.storage().alignment(), 4); CORRADE_COMPARE(b.storage().alignment(), 4);
CORRADE_COMPARE(b.format(), PixelFormat::Red); CORRADE_COMPARE(b.format(), GL::PixelFormat::Red);
CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); CORRADE_COMPARE(b.type(), PixelType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(4, 1)); CORRADE_COMPARE(b.size(), Vector2i(4, 1));
CORRADE_COMPARE(b.buffer().id(), id); CORRADE_COMPARE(b.buffer().id(), id);
@ -226,7 +226,7 @@ void BufferImageGLTest::constructMove() {
CORRADE_COMPARE(b.size(), Vector2i(1, 2)); CORRADE_COMPARE(b.size(), Vector2i(1, 2));
CORRADE_COMPARE(c.storage().alignment(), 4); CORRADE_COMPARE(c.storage().alignment(), 4);
CORRADE_COMPARE(c.format(), PixelFormat::Red); CORRADE_COMPARE(c.format(), GL::PixelFormat::Red);
CORRADE_COMPARE(c.type(), PixelType::UnsignedByte); CORRADE_COMPARE(c.type(), PixelType::UnsignedByte);
CORRADE_COMPARE(c.size(), Vector2i(4, 1)); CORRADE_COMPARE(c.size(), Vector2i(4, 1));
CORRADE_COMPARE(c.buffer().id(), id); CORRADE_COMPARE(c.buffer().id(), id);
@ -249,7 +249,7 @@ void BufferImageGLTest::constructMoveCompressed() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{0}); CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{0});
#endif #endif
CORRADE_COMPARE(b.format(), CompressedPixelFormat::RGBAS3tcDxt1); CORRADE_COMPARE(b.format(), GL::CompressedPixelFormat::RGBAS3tcDxt1);
CORRADE_COMPARE(b.size(), Vector2i(4, 4)); CORRADE_COMPARE(b.size(), Vector2i(4, 4));
CORRADE_COMPARE(b.dataSize(), 8); CORRADE_COMPARE(b.dataSize(), 8);
CORRADE_COMPARE(b.buffer().id(), id); CORRADE_COMPARE(b.buffer().id(), id);
@ -273,7 +273,7 @@ void BufferImageGLTest::constructMoveCompressed() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(c.storage().compressedBlockSize(), Vector3i{0}); CORRADE_COMPARE(c.storage().compressedBlockSize(), Vector3i{0});
#endif #endif
CORRADE_COMPARE(c.format(), CompressedPixelFormat::RGBAS3tcDxt1); CORRADE_COMPARE(c.format(), GL::CompressedPixelFormat::RGBAS3tcDxt1);
CORRADE_COMPARE(c.size(), Vector2i(4, 4)); CORRADE_COMPARE(c.size(), Vector2i(4, 4));
CORRADE_COMPARE(c.dataSize(), 8); CORRADE_COMPARE(c.dataSize(), 8);
CORRADE_COMPARE(c.buffer().id(), id); CORRADE_COMPARE(c.buffer().id(), id);
@ -294,7 +294,7 @@ void BufferImageGLTest::setData() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(a.storage().alignment(), 4); CORRADE_COMPARE(a.storage().alignment(), 4);
CORRADE_COMPARE(a.format(), PixelFormat::RGBA); CORRADE_COMPARE(a.format(), GL::PixelFormat::RGBA);
CORRADE_COMPARE(a.type(), PixelType::UnsignedShort); CORRADE_COMPARE(a.type(), PixelType::UnsignedShort);
CORRADE_COMPARE(a.size(), Vector2i(1, 2)); CORRADE_COMPARE(a.size(), Vector2i(1, 2));
@ -326,7 +326,7 @@ void BufferImageGLTest::setDataCompressed() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4});
#endif #endif
CORRADE_COMPARE(a.format(), CompressedPixelFormat::RGBAS3tcDxt3); CORRADE_COMPARE(a.format(), GL::CompressedPixelFormat::RGBAS3tcDxt3);
CORRADE_COMPARE(a.size(), Vector2i(8, 4)); CORRADE_COMPARE(a.size(), Vector2i(8, 4));
CORRADE_COMPARE(a.dataSize(), 16); CORRADE_COMPARE(a.dataSize(), 16);

4
src/Magnum/GL/Test/CMakeLists.txt

@ -26,7 +26,6 @@
corrade_add_test(GLAttributeTest AttributeTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLAttributeTest AttributeTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLAbstractShaderProgramTest AbstractShaderProgramTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLAbstractShaderProgramTest AbstractShaderProgramTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLBufferTest BufferTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLBufferTest BufferTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLFormatTest FormatTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLContextTest ContextTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLContextTest ContextTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLCubeMapTextureTest CubeMapTextureTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLCubeMapTextureTest CubeMapTextureTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLDefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLDefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES MagnumGL)
@ -34,6 +33,7 @@ corrade_add_test(GLFramebufferTest FramebufferTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLImageTest ../../Test/ImageTest.cpp LIBRARIES MagnumGL) # temporary corrade_add_test(GLImageTest ../../Test/ImageTest.cpp LIBRARIES MagnumGL) # temporary
corrade_add_test(GLImageViewTest ../../Test/ImageViewTest.cpp LIBRARIES MagnumGL) # temporary corrade_add_test(GLImageViewTest ../../Test/ImageViewTest.cpp LIBRARIES MagnumGL) # temporary
corrade_add_test(GLMeshTest MeshTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLMeshTest MeshTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLPixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumGLTestLib)
corrade_add_test(GLPixelStorageTest ../../Test/PixelStorageTest.cpp LIBRARIES MagnumGL) # temporary corrade_add_test(GLPixelStorageTest ../../Test/PixelStorageTest.cpp LIBRARIES MagnumGL) # temporary
corrade_add_test(GLRendererTest RendererTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLRendererTest RendererTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLRenderbufferTest RenderbufferTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLRenderbufferTest RenderbufferTest.cpp LIBRARIES MagnumGL)
@ -46,7 +46,6 @@ set_target_properties(
GLAttributeTest GLAttributeTest
GLAbstractShaderProgramTest GLAbstractShaderProgramTest
GLBufferTest GLBufferTest
GLFormatTest
GLContextTest GLContextTest
GLCubeMapTextureTest GLCubeMapTextureTest
GLDefaultFramebufferTest GLDefaultFramebufferTest
@ -55,6 +54,7 @@ set_target_properties(
GLImageViewTest GLImageViewTest
GLMeshTest GLMeshTest
GLPixelStorageTest GLPixelStorageTest
GLPixelFormatTest
GLRendererTest GLRendererTest
GLRenderbufferTest GLRenderbufferTest
GLSamplerTest GLSamplerTest

74
src/Magnum/GL/Test/FormatTest.cpp

@ -1,74 +0,0 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/PixelFormat.h"
namespace Magnum { namespace Test {
struct FormatTest: TestSuite::Tester {
explicit FormatTest();
void debugPixelFormat();
void debugPixelType();
void debugCompressedPixelFormat();
};
FormatTest::FormatTest() {
addTests({&FormatTest::debugPixelFormat,
&FormatTest::debugPixelType,
&FormatTest::debugCompressedPixelFormat});
}
void FormatTest::debugPixelFormat() {
std::ostringstream out;
Debug(&out) << PixelFormat::RGBA << PixelFormat(0xdead);
CORRADE_COMPARE(out.str(), "GL::PixelFormat::RGBA GL::PixelFormat(0xdead)\n");
}
void FormatTest::debugPixelType() {
std::ostringstream out;
Debug(&out) << PixelType::UnsignedByte << PixelType(0xdead);
CORRADE_COMPARE(out.str(), "GL::PixelType::UnsignedByte GL::PixelType(0xdead)\n");
}
void FormatTest::debugCompressedPixelFormat() {
#ifdef MAGNUM_TARGET_GLES
CORRADE_SKIP("No enum value available");
#else
std::ostringstream out;
Debug(&out) << CompressedPixelFormat::RGBBptcUnsignedFloat << CompressedPixelFormat(0xdead);
CORRADE_COMPARE(out.str(), "GL::CompressedPixelFormat::RGBBptcUnsignedFloat GL::CompressedPixelFormat(0xdead)\n");
#endif
}
}}
CORRADE_TEST_MAIN(Magnum::Test::FormatTest)

548
src/Magnum/GL/Test/PixelFormatTest.cpp

@ -0,0 +1,548 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/PixelFormat.h"
#include "Magnum/GL/PixelFormat.h"
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
#include "Magnum/PixelStorage.h"
#endif
namespace Magnum { namespace GL { namespace Test {
struct PixelFormatTest: TestSuite::Tester {
explicit PixelFormatTest();
void mapFormatType();
void mapFormatImplementationSpecific();
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void mapFormatDeprecated();
#endif
void mapFormatUnsupported();
void mapFormatInvalid();
void mapTypeImplementationSpecific();
void mapTypeImplementationSpecificZero();
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void mapTypeDeprecated();
#endif
void mapTypeUnsupported();
void mapTypeInvalid();
void size();
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void sizeDataPropertiesDeprecated();
#endif
void sizeInvalid();
void mapCompressedFormat();
void mapCompressedFormatImplementationSpecific();
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void mapCompressedFormatDeprecated();
#endif
void mapCompressedFormatUnsupported();
void mapCompressedFormatInvalid();
void debugPixelFormat();
void debugPixelType();
void debugCompressedPixelFormat();
};
PixelFormatTest::PixelFormatTest() {
addTests({&PixelFormatTest::mapFormatType,
&PixelFormatTest::mapFormatImplementationSpecific,
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
&PixelFormatTest::mapFormatDeprecated,
#endif
&PixelFormatTest::mapFormatUnsupported,
&PixelFormatTest::mapFormatInvalid,
&PixelFormatTest::mapTypeImplementationSpecific,
&PixelFormatTest::mapTypeImplementationSpecificZero,
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
&PixelFormatTest::mapTypeDeprecated,
#endif
&PixelFormatTest::mapTypeUnsupported,
&PixelFormatTest::mapTypeInvalid,
&PixelFormatTest::size,
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
&PixelFormatTest::sizeDataPropertiesDeprecated,
#endif
&PixelFormatTest::sizeInvalid,
&PixelFormatTest::mapCompressedFormat,
&PixelFormatTest::mapCompressedFormatImplementationSpecific,
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
&PixelFormatTest::mapCompressedFormatDeprecated,
#endif
&PixelFormatTest::mapCompressedFormatUnsupported,
&PixelFormatTest::mapCompressedFormatInvalid,
&PixelFormatTest::debugPixelFormat,
&PixelFormatTest::debugPixelType,
&PixelFormatTest::debugCompressedPixelFormat});
}
void PixelFormatTest::mapFormatType() {
/* Touchstone verification */
CORRADE_VERIFY(hasPixelFormat(Magnum::PixelFormat::RGBA8Unorm));
CORRADE_COMPARE(pixelFormat(Magnum::PixelFormat::RGBA8Unorm), PixelFormat::RGBA);
CORRADE_COMPARE(pixelType(Magnum::PixelFormat::RGBA8Unorm), PixelType::UnsignedByte);
/* This goes through the first 16 bits, which should be enough. Going
through 32 bits takes 8 seconds, too much. */
UnsignedInt firstUnhandled = 0xffff;
UnsignedInt nextHandled = 0;
for(UnsignedInt i = 0; i <= 0xffff; ++i) {
const auto format = Magnum::PixelFormat(i);
/* Each case verifies:
- that the cases are ordered by number (so insertion here is done in
proper place)
- that there was no gap (unhandled value inside the range)
- that a particular pixel format maps to a particular GL format
- that a particular pixel type maps to a particular GL type */
switch(format) {
#define _c(format, expectedFormat, expectedType) \
case Magnum::PixelFormat::format: \
CORRADE_COMPARE(nextHandled, i); \
CORRADE_COMPARE(firstUnhandled, 0xffff); \
CORRADE_VERIFY(hasPixelFormat(Magnum::PixelFormat::format)); \
CORRADE_COMPARE(pixelFormat(Magnum::PixelFormat::format), Magnum::GL::PixelFormat::expectedFormat); \
CORRADE_COMPARE(pixelType(Magnum::PixelFormat::format), Magnum::GL::PixelType::expectedType); \
++nextHandled; \
continue;
#define _s(format) \
case Magnum::PixelFormat::format: \
CORRADE_COMPARE(nextHandled, i); \
CORRADE_COMPARE(firstUnhandled, 0xffff); \
CORRADE_VERIFY(!hasPixelFormat(Magnum::PixelFormat::format)); \
pixelFormat(Magnum::PixelFormat::format); \
pixelType(Magnum::PixelFormat::format); \
++nextHandled; \
continue;
#include "Magnum/GL/Implementation/pixelFormatMapping.hpp"
#undef _s
#undef _c
/* Here to silence unhandled value warnings and to verify that all
GL-specific formats are larger than a particular value. This
value is used in pixelFormat() and pixelType() to detect
deprecated GL-specific values and convert them properly. */
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
#define _c(value) \
case Magnum::PixelFormat::value: \
CORRADE_VERIFY(UnsignedInt(Magnum::PixelFormat::value) >= 0x1000); \
continue;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4996)
#endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
_c(Red)
#endif
#ifndef MAGNUM_TARGET_GLES
_c(Green)
_c(Blue)
#endif
#ifdef MAGNUM_TARGET_GLES2
_c(Luminance)
#endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
_c(RG)
#endif
#ifdef MAGNUM_TARGET_GLES2
_c(LuminanceAlpha)
#endif
_c(RGB)
_c(RGBA)
#ifndef MAGNUM_TARGET_GLES
_c(BGR)
#endif
#ifndef MAGNUM_TARGET_WEBGL
_c(BGRA)
#endif
#ifdef MAGNUM_TARGET_GLES2
_c(SRGB)
_c(SRGBAlpha)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(RedInteger)
#ifndef MAGNUM_TARGET_GLES
_c(GreenInteger)
_c(BlueInteger)
#endif
_c(RGInteger)
_c(RGBInteger)
_c(RGBAInteger)
#ifndef MAGNUM_TARGET_GLES
_c(BGRInteger)
_c(BGRAInteger)
#endif
#endif
_c(DepthComponent)
#ifndef MAGNUM_TARGET_WEBGL
_c(StencilIndex)
#endif
_c(DepthStencil)
#undef _c
#ifdef __GNUC__
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif
}
/* Not handled by any value, remember -- we might either be at the end
of the enum range (which is okay) or some value might be unhandled
here */
firstUnhandled = i;
}
CORRADE_COMPARE(firstUnhandled, 0xffff);
}
void PixelFormatTest::mapFormatImplementationSpecific() {
CORRADE_VERIFY(hasPixelFormat(Magnum::pixelFormatWrap(PixelFormat::RGBA)));
CORRADE_COMPARE(pixelFormat(Magnum::pixelFormatWrap(PixelFormat::RGBA)),
PixelFormat::RGBA);
}
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void PixelFormatTest::mapFormatDeprecated() {
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_COMPARE(pixelFormat(Magnum::PixelFormat::RGBA),
PixelFormat::RGBA);
CORRADE_IGNORE_DEPRECATED_POP
}
#endif
void PixelFormatTest::mapFormatUnsupported() {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_SKIP("All pixel formats are supported on ES3+");
#else
std::ostringstream out;
Error redirectError{&out};
pixelFormat(Magnum::PixelFormat::RGB16UI);
CORRADE_COMPARE(out.str(), "GL::pixelFormat(): format PixelFormat::RGB16UI is not supported on this target\n");
#endif
}
void PixelFormatTest::mapFormatInvalid() {
std::ostringstream out;
Error redirectError{&out};
hasPixelFormat(Magnum::PixelFormat(0x123));
pixelFormat(Magnum::PixelFormat(0x123));
CORRADE_COMPARE(out.str(),
"GL::hasPixelFormat(): invalid format PixelFormat(0x123)\n"
"GL::pixelFormat(): invalid format PixelFormat(0x123)\n");
}
void PixelFormatTest::mapTypeImplementationSpecific() {
CORRADE_COMPARE(pixelType(Magnum::pixelFormatWrap(PixelFormat::RGBA), GL_UNSIGNED_BYTE),
PixelType::UnsignedByte);
}
void PixelFormatTest::mapTypeImplementationSpecificZero() {
std::ostringstream out;
Error redirectError{&out};
pixelType(Magnum::pixelFormatWrap(PixelFormat::RGBA));
CORRADE_COMPARE(out.str(), "GL::pixelType(): format is implementation-specific, but no additional type specifier was passed\n");
}
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void PixelFormatTest::mapTypeDeprecated() {
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_COMPARE(pixelType(Magnum::PixelFormat::RGBA, GL_UNSIGNED_BYTE),
PixelType::UnsignedByte);
CORRADE_IGNORE_DEPRECATED_POP
}
#endif
void PixelFormatTest::mapTypeUnsupported() {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_SKIP("All pixel formats are supported on ES3+");
#else
CORRADE_VERIFY(!hasPixelFormat(Magnum::PixelFormat::RGBA16UI));
std::ostringstream out;
Error redirectError{&out};
pixelType(Magnum::PixelFormat::RGB16UI);
CORRADE_COMPARE(out.str(), "GL::pixelType(): format PixelFormat::RGB16UI is not supported on this target\n");
#endif
}
void PixelFormatTest::mapTypeInvalid() {
std::ostringstream out;
Error redirectError{&out};
pixelType(Magnum::PixelFormat(0x123));
CORRADE_COMPARE(out.str(), "GL::pixelType(): invalid format PixelFormat(0x123)\n");
}
void PixelFormatTest::size() {
#ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(pixelSize(PixelFormat::RGB, PixelType::UnsignedByte332), 1);
#endif
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE(pixelSize(PixelFormat::StencilIndex, PixelType::UnsignedByte), 1);
#endif
CORRADE_COMPARE(pixelSize(PixelFormat::DepthComponent, PixelType::UnsignedShort), 2);
CORRADE_COMPARE(pixelSize(PixelFormat::RGBA, PixelType::UnsignedShort4444), 2);
CORRADE_COMPARE(pixelSize(PixelFormat::DepthStencil, PixelType::UnsignedInt248), 4);
CORRADE_COMPARE(pixelSize(PixelFormat::RGBA, PixelType::UnsignedInt), 4*4);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_COMPARE(pixelSize(PixelFormat::DepthStencil, PixelType::Float32UnsignedInt248Rev), 8);
#endif
}
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void PixelFormatTest::sizeDataPropertiesDeprecated() {
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::RGBA, PixelType::UnsignedShort4444), 2);
CORRADE_IGNORE_DEPRECATED_POP
PixelStorage storage;
storage.setAlignment(4)
.setRowLength(15)
.setSkip({3, 7, 0});
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}),
(std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t>{{3*4, 7*15*4, 0}, {60, 1, 1}, 4}));
CORRADE_IGNORE_DEPRECATED_POP
}
#endif
void PixelFormatTest::sizeInvalid() {
std::ostringstream out;
Error redirectError{&out};
pixelSize(PixelFormat::DepthStencil, PixelType::Float);
CORRADE_COMPARE(out.str(), "GL::pixelSize(): invalid GL::PixelType::Float specified for GL::PixelFormat::DepthStencil\n");
}
void PixelFormatTest::mapCompressedFormat() {
/* Touchstone verification */
CORRADE_VERIFY(hasCompressedPixelFormat(Magnum::CompressedPixelFormat::Bc1RGBAUnorm));
CORRADE_COMPARE(compressedPixelFormat(Magnum::CompressedPixelFormat::Bc1RGBAUnorm), CompressedPixelFormat::RGBAS3tcDxt1);
/* This goes through the first 16 bits, which should be enough. Going
through 32 bits takes 8 seconds, too much. */
UnsignedInt firstUnhandled = 0xffff;
UnsignedInt nextHandled = 0;
for(UnsignedInt i = 0; i <= 0xffff; ++i) {
const auto format = Magnum::CompressedPixelFormat(i);
/* Each case verifies:
- that the cases are ordered by number (so insertion here is done in
proper place)
- that there was no gap (unhandled value inside the range)
- that a particular pixel format maps to a particular GL format
- that a particular pixel type maps to a particular GL type */
switch(format) {
#define _c(format, expectedFormat) \
case Magnum::CompressedPixelFormat::format: \
CORRADE_COMPARE(nextHandled, i); \
CORRADE_COMPARE(firstUnhandled, 0xffff); \
CORRADE_VERIFY(hasCompressedPixelFormat(Magnum::CompressedPixelFormat::format)); \
CORRADE_COMPARE(compressedPixelFormat(Magnum::CompressedPixelFormat::format), Magnum::GL::CompressedPixelFormat::expectedFormat); \
++nextHandled; \
continue;
#define _s(format) \
case Magnum::CompressedPixelFormat::format: \
CORRADE_COMPARE(nextHandled, i); \
CORRADE_COMPARE(firstUnhandled, 0xffff); \
CORRADE_VERIFY(!hasCompressedPixelFormat(Magnum::CompressedPixelFormat::format)); \
compressedPixelFormat(Magnum::CompressedPixelFormat::format); \
++nextHandled; \
continue;
#include "Magnum/GL/Implementation/compressedPixelFormatMapping.hpp"
#undef _s
#undef _c
/* Here to silence unhandled value warnings and to verify that all
GL-specific formats are larger than a particular value. This
value is used in compressedPixelFormat() to detect deprecated
GL-specific values and convert them properly. */
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
#define _c(value) \
case Magnum::CompressedPixelFormat::value: \
CORRADE_VERIFY(UnsignedInt(Magnum::CompressedPixelFormat::value) >= 0x1000); \
continue;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4996)
#endif
#ifndef MAGNUM_TARGET_GLES
_c(Red)
_c(RG)
_c(RGB)
_c(RGBA)
_c(RedRgtc1)
_c(RGRgtc2)
_c(SignedRedRgtc1)
_c(SignedRGRgtc2)
_c(RGBBptcUnsignedFloat)
_c(RGBBptcSignedFloat)
_c(RGBABptcUnorm)
_c(SRGBAlphaBptcUnorm)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(RGB8Etc2)
_c(SRGB8Etc2)
_c(RGB8PunchthroughAlpha1Etc2)
_c(SRGB8PunchthroughAlpha1Etc2)
_c(RGBA8Etc2Eac)
_c(SRGB8Alpha8Etc2Eac)
_c(R11Eac)
_c(SignedR11Eac)
_c(RG11Eac)
_c(SignedRG11Eac)
#endif
_c(RGBS3tcDxt1)
_c(RGBAS3tcDxt1)
_c(RGBAS3tcDxt3)
_c(RGBAS3tcDxt5)
#ifndef MAGNUM_TARGET_WEBGL
_c(RGBAAstc4x4)
_c(SRGB8Alpha8Astc4x4)
_c(RGBAAstc5x4)
_c(SRGB8Alpha8Astc5x4)
_c(RGBAAstc5x5)
_c(SRGB8Alpha8Astc5x5)
_c(RGBAAstc6x5)
_c(SRGB8Alpha8Astc6x5)
_c(RGBAAstc6x6)
_c(SRGB8Alpha8Astc6x6)
_c(RGBAAstc8x5)
_c(SRGB8Alpha8Astc8x5)
_c(RGBAAstc8x6)
_c(SRGB8Alpha8Astc8x6)
_c(RGBAAstc8x8)
_c(SRGB8Alpha8Astc8x8)
_c(RGBAAstc10x5)
_c(SRGB8Alpha8Astc10x5)
_c(RGBAAstc10x6)
_c(SRGB8Alpha8Astc10x6)
_c(RGBAAstc10x8)
_c(SRGB8Alpha8Astc10x8)
_c(RGBAAstc10x10)
_c(SRGB8Alpha8Astc10x10)
_c(RGBAAstc12x10)
_c(SRGB8Alpha8Astc12x10)
_c(RGBAAstc12x12)
_c(SRGB8Alpha8Astc12x12)
#endif
#undef _c
#ifdef __GNUC__
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif
}
/* Not handled by any value, remember -- we might either be at the end
of the enum range (which is okay) or some value might be unhandled
here */
firstUnhandled = i;
}
CORRADE_COMPARE(firstUnhandled, 0xffff);
}
void PixelFormatTest::mapCompressedFormatImplementationSpecific() {
CORRADE_VERIFY(hasCompressedPixelFormat(Magnum::compressedPixelFormatWrap(CompressedPixelFormat::RGBAS3tcDxt1)));
CORRADE_COMPARE(compressedPixelFormat(Magnum::compressedPixelFormatWrap(CompressedPixelFormat::RGBAS3tcDxt1)),
CompressedPixelFormat::RGBAS3tcDxt1);
}
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void PixelFormatTest::mapCompressedFormatDeprecated() {
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_COMPARE(compressedPixelFormat(Magnum::CompressedPixelFormat::RGBAS3tcDxt1),
CompressedPixelFormat::RGBAS3tcDxt1);
CORRADE_IGNORE_DEPRECATED_POP
}
#endif
void PixelFormatTest::mapCompressedFormatUnsupported() {
#if 1
CORRADE_SKIP("All compressed pixel formats are currently supported everywhere");
#else
CORRADE_VERIFY(!hasCompressedPixelFormat(Magnum::CompressedPixelFormat::Bc1RGBAUnorm));
std::ostringstream out;
Error redirectError{&out};
compressedPixelFormat(Magnum::CompressedPixelFormat::Bc1RGBAUnorm);
CORRADE_COMPARE(out.str(), "GL::compressedPixelFormat(): format CompressedPixelFormat::Bc1RGBAUnorm is not supported on this target\n");
#endif
}
void PixelFormatTest::mapCompressedFormatInvalid() {
std::ostringstream out;
Error redirectError{&out};
hasCompressedPixelFormat(Magnum::CompressedPixelFormat(0x123));
compressedPixelFormat(Magnum::CompressedPixelFormat(0x123));
CORRADE_COMPARE(out.str(),
"GL::hasCompressedPixelFormat(): invalid format CompressedPixelFormat(0x123)\n"
"GL::compressedPixelFormat(): invalid format CompressedPixelFormat(0x123)\n");
}
void PixelFormatTest::debugPixelFormat() {
std::ostringstream out;
Debug(&out) << PixelFormat::RGBA << PixelFormat(0xdead);
CORRADE_COMPARE(out.str(), "GL::PixelFormat::RGBA GL::PixelFormat(0xdead)\n");
}
void PixelFormatTest::debugPixelType() {
std::ostringstream out;
Debug(&out) << PixelType::UnsignedByte << PixelType(0xdead);
CORRADE_COMPARE(out.str(), "GL::PixelType::UnsignedByte GL::PixelType(0xdead)\n");
}
void PixelFormatTest::debugCompressedPixelFormat() {
std::ostringstream out;
Debug{&out} << CompressedPixelFormat::RGBS3tcDxt1 << CompressedPixelFormat(0xdead);
CORRADE_COMPARE(out.str(), "GL::CompressedPixelFormat::RGBS3tcDxt1 GL::CompressedPixelFormat(0xdead)\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::GL::Test::PixelFormatTest)

2
src/Magnum/GL/visibility.h

@ -31,7 +31,7 @@
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_BUILD_STATIC #ifndef MAGNUM_BUILD_STATIC
#ifdef MagnumGL_EXPORTS #if defined(MagnumGL_EXPORTS) || defined(MagnumGLObjects_EXPORTS)
#define MAGNUM_GL_EXPORT CORRADE_VISIBILITY_EXPORT #define MAGNUM_GL_EXPORT CORRADE_VISIBILITY_EXPORT
#else #else
#define MAGNUM_GL_EXPORT CORRADE_VISIBILITY_IMPORT #define MAGNUM_GL_EXPORT CORRADE_VISIBILITY_IMPORT

32
src/Magnum/Image.cpp

@ -25,20 +25,38 @@
#include "Image.h" #include "Image.h"
#include "Magnum/PixelFormat.h"
namespace Magnum { namespace Magnum {
template<UnsignedInt dimensions> Image<dimensions>::Image(PixelStorage storage, GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: _storage{storage}, _format{format}, _type{type}, _size{size}, _data{std::move(data)} { template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage, format, {}, Magnum::pixelSize(format), size, std::move(data)} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data)} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _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), ); CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Image::Image(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), );
} }
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format) noexcept: Image{storage, format, {}, Magnum::pixelSize(format)} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize) noexcept: Image{storage, pixelFormatWrap(format), formatExtra, pixelSize} {}
template<UnsignedInt dimensions> Image<dimensions>::Image(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _data{} {}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: _storage{storage}, _format{format}, _size{size}, _data{std::move(data)} {}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{storage, compressedPixelFormatWrap(format), size, std::move(data)} {}
template<UnsignedInt dimensions> CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage) noexcept: _storage{storage}, _format{} {}
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
template class MAGNUM_GL_EXPORT Image<1>; template class MAGNUM_EXPORT Image<1>;
template class MAGNUM_GL_EXPORT Image<2>; template class MAGNUM_EXPORT Image<2>;
template class MAGNUM_GL_EXPORT Image<3>; template class MAGNUM_EXPORT Image<3>;
template class MAGNUM_GL_EXPORT CompressedImage<1>; template class MAGNUM_EXPORT CompressedImage<1>;
template class MAGNUM_GL_EXPORT CompressedImage<2>; template class MAGNUM_EXPORT CompressedImage<2>;
template class MAGNUM_GL_EXPORT CompressedImage<3>; template class MAGNUM_EXPORT CompressedImage<3>;
#endif #endif
} }

505
src/Magnum/Image.h

@ -38,8 +38,37 @@ namespace Magnum {
/** /**
@brief Image @brief Image
Stores image data on client memory. Interchangeable with @ref ImageView, Stores multi-dimensional image data together with layout and pixel format
@ref BufferImage or @ref Trade::ImageData. description. See @ref ImageView for a non-owning alternative.
This class can act as a drop-in replacement for @ref ImageView and
@ref Trade::ImageData APIs and is implicitly convertible to @ref ImageView.
Particular graphics API wrappers provide additional image classes, for example
@ref GL::BufferImage. See also @ref CompressedImage for equivalent
functionality targeted on compressed image formats.
@section Image-usage Basic usage
The image takes ownership of a passed @ref Corrade::Containers::Array, together
with storing image size and one of the generic @ref PixelFormat values:
@snippet Magnum.cpp Image-usage
On construction, the image internally calculates pixel size corresponding to
given pixel format using @ref pixelSize(). This value is needed to check that
the passed data array is large enough and is also required by most image
manipulation operations.
It's also possible to create just an image placeholder, storing only the image
properties without data or size. That is useful for example to specify desired
format of image queries in graphics APIs:
@snippet Magnum.cpp Image-usage-query
As with @ref ImageView, this class supports extra storage parameters and
implementation-specific pixel format specification. See the @ref ImageView
documentation for more information.
@see @ref Image1D, @ref Image2D, @ref Image3D, @ref CompressedImage @see @ref Image1D, @ref Image2D, @ref Image3D, @ref CompressedImage
*/ */
template<UnsignedInt dimensions> class Image { template<UnsignedInt dimensions> class Image {
@ -52,39 +81,185 @@ template<UnsignedInt dimensions> class Image {
* @brief Constructor * @brief Constructor
* @param storage Storage of pixel data * @param storage Storage of pixel data
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
* *
* The data are expected to be of proper size for given @p storage * The @p data array is expected to be of proper size for given
* parameters.
*/
explicit Image(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
/**
* @brief Constructor
* @param format Format of pixel data
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref Image(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* with default-constructed @ref PixelStorage.
*/
explicit Image(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{{}, format, size, std::move(data)} {}
/**
* @brief Construct an image placeholder
* @param storage Storage of pixel data
* @param format Format of pixel data
*
* Size is set to zero and data pointer to @cpp nullptr @ce. Move over
* a non-empty instance to make it useful.
*/
/*implicit*/ Image(PixelStorage storage, PixelFormat format) noexcept;
/**
* @brief Construct an image placeholder
* @param format Format of pixel data
*
* Equivalent to calling @ref Image(PixelStorage, PixelFormat)
* with default-constructed @ref PixelStorage.
*/
/*implicit*/ Image(PixelFormat format) noexcept: Image{{}, format} {}
/**
* @brief Construct an image with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param pixelSize Size of a pixel in given format
* @param size Image size
* @param data Image data
*
* Unlike with @ref Image(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&),
* where pixel size is calculated automatically using
* @ref pixelSize(PixelFormat), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
* @ref pixelFormatWrap() internally to wrap @p format in
* @ref PixelFormat.
*
* The @p data array is expected to be of proper size for given
* parameters. * parameters.
*/ */
explicit Image(PixelStorage storage, GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept; explicit Image(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
/** @overload /** @overload
* Similar to the above, but uses default @ref PixelStorage parameters. *
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/ */
explicit Image(GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{{}, format, type, size, std::move(data)} {} explicit Image(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
/** /**
* @brief Constructor * @brief Construct an image placeholder with implementation-specific pixel format
* @param storage Storage of pixel data * @param storage Storage of pixel data
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data * @param formatExtra Additional pixel format specifier
* @param pixelSize Size of a pixel in given format
* *
* Dimensions are set to zero and data pointer to @cpp nullptr @ce, * Unlike with @ref Image(PixelStorage, PixelFormat), where pixel size
* call @ref setData() to fill the image with data or use * is calculated automatically using @ref pixelSize(PixelFormat), this
* @ref Texture::image() "*Texture::image()"/ * allows you to specify an implementation-specific pixel format and
* @ref Texture::subImage() "*Texture::subImage()"/ * pixel size directly. Uses @ref pixelFormatWrap() internally to
* @ref AbstractFramebuffer::read() "*Framebuffer::read()" to fill the * wrap @p format in @ref PixelFormat.
* image with data using @p storage settings.
*/ */
/*implicit*/ Image(PixelStorage storage, GL::PixelFormat format, GL::PixelType type) noexcept: _storage{storage}, _format{format}, _type{type}, _data{} {} explicit Image(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize) noexcept;
/** @overload /** @overload
* Similar to the above, but uses default @ref PixelStorage parameters. *
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/
explicit Image(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize) noexcept;
/**
* @brief Construct an image with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
*
* Uses ADL to find a corresponding @cpp pixelSize(T, U) @ce overload,
* then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* with calculated pixel size.
*/
template<class T, class U> explicit Image(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
/**
* @brief Construct an image with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
*
* Uses ADL to find a corresponding @cpp pixelSize(T) @ce overload,
* then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/
template<class T> explicit Image(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
/**
* @brief Construct an image with implementation-specific pixel format
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref Image(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* with default-constructed @ref PixelStorage.
*/
template<class T, class U> explicit Image(T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{{}, format, formatExtra, size, std::move(data)} {}
/**
* @brief Construct an image with implementation-specific pixel format
* @param format Format of pixel data
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref Image(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* with default-constructed @ref PixelStorage.
*/
template<class T> explicit Image(T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{{}, format, size, std::move(data)} {}
/**
* @brief Construct an image placeholder with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
*
* Uses ADL to find a corresponding @cpp pixelSize(T, U) @ce overload,
* then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt)
* with calculated pixel size.
*/
template<class T, class U> /*implicit*/ Image(PixelStorage storage, T format, U formatExtra) noexcept;
/**
* @brief Construct an image placeholder with implementation-specific pixel format
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
*
* Equivalent to calling @ref Image(PixelStorage, T, U) with
* default-constructed @ref PixelStorage.
*/
template<class T, class U> /*implicit*/ Image(T format, U formatExtra) noexcept: Image{{}, format, formatExtra} {}
/**
* @brief Construct an image placeholder with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
*
* Uses ADL to find a corresponding @cpp pixelSize(T) @ce overload,
* then calls @ref Image(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/
template<class T> /*implicit*/ Image(PixelStorage storage, T format) noexcept;
/**
* @brief Construct an image placeholder with implementation-specific pixel format
* @param format Format of pixel data
*
* Equivalent to calling @ref Image(PixelStorage, T) with
* default-constructed @ref PixelStorage.
*/ */
/*implicit*/ Image(GL::PixelFormat format, GL::PixelType type) noexcept: Image{{}, format, type} {} template<class T> /*implicit*/ Image(T format) noexcept: Image{{}, format} {}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Image(const Image<dimensions>&) = delete; Image(const Image<dimensions>&) = delete;
@ -106,18 +281,41 @@ template<UnsignedInt dimensions> class Image {
/** @brief Storage of pixel data */ /** @brief Storage of pixel data */
PixelStorage storage() const { return _storage; } PixelStorage storage() const { return _storage; }
/** @brief Format of pixel data */ /**
GL::PixelFormat format() const { return _format; } * @brief Format of pixel data
*
* Returns either a defined value from the @ref PixelFormat enum or a
* wrapped implementation-specific value. Use
* @ref isPixelFormatImplementationSpecific() to distinguish the case
* and @ref pixelFormatUnwrap() to extract an implementation-specific
* value, if needed.
* @see @ref formatExtra()
*/
PixelFormat format() const { return _format; }
/**
* @brief Additional pixel format specifier
*
* Some implementations (such as OpenGL) define a pixel format using
* two values. This field contains the second implementation-specific
* value verbatim, if any. See @ref format() for more information.
*/
UnsignedInt formatExtra() const { return _formatExtra; }
/** @brief Data type of pixel data */ #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
GL::PixelType type() const { return _type; } /**
* @brief Data type of pixel data
* @deprecated Cast @ref formatExtra() to @ref GL::PixelType instead.
*/
CORRADE_DEPRECATED("cast formatExtra() to GL::PixelType instead") GL::PixelType type() const { return GL::PixelType(_formatExtra); }
#endif
/** /**
* @brief Pixel size (in bytes) * @brief Pixel size (in bytes)
* *
* @see @ref PixelStorage::pixelSize() * @see @ref pixelSize(PixelFormat)
*/ */
std::size_t pixelSize() const { return PixelStorage::pixelSize(_format, _type); } UnsignedInt pixelSize() const { return _pixelSize; }
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<dimensions, Int> size() const { return _size; } VectorTypeFor<dimensions, Int> size() const { return _size; }
@ -165,48 +363,56 @@ template<UnsignedInt dimensions> class Image {
return reinterpret_cast<const T*>(_data.data()); return reinterpret_cast<const T*>(_data.data());
} }
#ifdef MAGNUM_BUILD_DEPRECATED #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/** /**
* @brief Set image data * @brief Set image data
* @param storage Storage of pixel data * @param storage Storage of pixel data
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data * @param formatExtra Additional pixel format specifier
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
* *
* @deprecated Move-assign a new instance instead. * @deprecated Move-assign a new instance instead.
* *
* Deletes previous data and replaces them with new. The data are * Deletes previous data and replaces them with new. The @p data array
* expected to be of proper size for given @p storage parameters. * is expected to be of proper size for given parameters.
* @see @ref release() * @see @ref release()
*/ */
CORRADE_DEPRECATED("move-assign a new instance instead") void setData(PixelStorage storage, GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) { template<class T, class U> CORRADE_DEPRECATED("move-assign a new instance instead") void setData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) {
*this = Image<dimensions>{storage, format, type, size, std::move(data)}; *this = Image<dimensions>{storage, format, formatExtra, size, std::move(data)};
} }
/** @overload /**
* Similar to the above, but uses default @ref PixelStorage parameters. * @brief Set image data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
* *
* @deprecated Move-assign a new instance instead. * @deprecated Move-assign a new instance instead.
*
* Equivalent to calling @ref setData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* with default-constructed @ref PixelStorage.
*/ */
CORRADE_DEPRECATED("move-assign a new instance instead") void setData(GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) { template<class T, class U> CORRADE_DEPRECATED("move-assign a new instance instead") void setData(T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) {
*this = Image<dimensions>{format, type, size, std::move(data)}; *this = Image<dimensions>{format, formatExtra, size, std::move(data)};
} }
#endif #endif
/** /**
* @brief Release data storage * @brief Release data storage
* *
* Releases the ownership of the data array and resets internal state * Releases the ownership of the data array and resets @ref size() to
* to default. * zero. The state afterwards is equivalent to moved-from state.
* @see @ref data() * @see @ref data()
*/ */
Containers::Array<char> release(); Containers::Array<char> release();
private: private:
PixelStorage _storage; PixelStorage _storage;
GL::PixelFormat _format; PixelFormat _format;
GL::PixelType _type; UnsignedInt _formatExtra;
UnsignedInt _pixelSize;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
Containers::Array<char> _data; Containers::Array<char> _data;
}; };
@ -223,10 +429,34 @@ typedef Image<3> Image3D;
/** /**
@brief Compressed image @brief Compressed image
Stores image data in client memory. Stores multi-dimensional compressed image data together with layout and
compressed block format description. See @ref CompressedImageView for a
non-owning alternative.
This class can act as a drop-in replacement for @ref CompressedImageView and
@ref Trade::ImageData APIs and is implicitly convertible to
@ref CompressedImageView. Particular graphics API wrappers provide additional
image classes, for example @ref GL::CompressedBufferImage. See also @ref Image
for equivalent functionality targeted on non-compressed image formats.
@section CompressedImage-usage Basic usage
The image takes ownership of a passed @ref Corrade::Containers::Array, together
with storing image size and one of the generic @ref CompressedPixelFormat
values:
@snippet Magnum.cpp CompressedImage-usage
It's also possible to create just an image placeholder, storing only the image
properties without data or size. That is useful for example to specify desired
format of image queries in graphics APIs:
@snippet Magnum.cpp CompressedImage-usage-query
As with @ref CompressedImageView, this class supports extra storage parameters
and implementation-specific compressed pixel format specification. See its
documentation for more information.
See @ref Image for more information. Interchangeable with
@ref CompressedImageView, @ref CompressedBufferImage or @ref Trade::ImageData.
@see @ref CompressedImage1D, @ref CompressedImage2D, @ref CompressedImage3D @see @ref CompressedImage1D, @ref CompressedImage2D, @ref CompressedImage3D
*/ */
template<UnsignedInt dimensions> class CompressedImage { template<UnsignedInt dimensions> class CompressedImage {
@ -235,20 +465,14 @@ template<UnsignedInt dimensions> class CompressedImage {
Dimensions = dimensions /**< Image dimension count */ Dimensions = dimensions /**< Image dimension count */
}; };
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Constructor * @brief Constructor
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data * @param format Format of compressed pixel data
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
*
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
explicit CompressedImage(CompressedPixelStorage storage, GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data); explicit CompressedImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
#endif
/** /**
* @brief Constructor * @brief Constructor
@ -256,36 +480,50 @@ template<UnsignedInt dimensions> class CompressedImage {
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref CompressedImage(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/ */
explicit CompressedImage(GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data); explicit CompressedImage(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{{}, format, size, std::move(data)} {}
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Constructor * @brief Construct a compressed image with implementation-specific format
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat.
*/
template<class T> explicit CompressedImage(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
/**
* @brief Construct a compressed image with implementation-specific format
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* *
* Format is undefined, size is zero and data are empty, call * Equivalent to calling @ref CompressedImage(CompressedPixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* @ref setData() to fill the image with data or use * with default-constructed @ref CompressedPixelStorage.
* @ref Texture::compressedImage() "*Texture::compressedImage()"/ */
* @ref Texture::compressedSubImage() "*Texture::compressedSubImage()" template<class T> explicit CompressedImage(T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{{}, format, size, std::move(data)} {}
* to fill the image with data using @p storage settings.
/**
* @brief Construct an image placeholder
* @param storage Storage of compressed pixel data
* *
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} * Format is undefined, size is zero and data is @cpp nullptr @ce. Move
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * over a non-empty instance to make it useful.
* WebGL.
*/ */
/*implicit*/ CompressedImage(CompressedPixelStorage storage); /*implicit*/ CompressedImage(CompressedPixelStorage storage) noexcept;
#endif
/** /**
* @brief Constructor * @brief Construct an image placeholder
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref CompressedImage(CompressedPixelStorage)
* parameters (or the hardcoded ones in OpenGL ES). * with default-constructed @ref CompressedPixelStorage.
*/ */
/*implicit*/ CompressedImage(); /*implicit*/ CompressedImage() noexcept: CompressedImage{{}} {}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
CompressedImage(const CompressedImage<dimensions>&) = delete; CompressedImage(const CompressedImage<dimensions>&) = delete;
@ -302,37 +540,32 @@ template<UnsignedInt dimensions> class CompressedImage {
/** @brief Conversion to view */ /** @brief Conversion to view */
/*implicit*/ operator CompressedImageView<dimensions>() const; /*implicit*/ operator CompressedImageView<dimensions>() const;
#ifndef MAGNUM_TARGET_GLES /** @brief Storage of compressed pixel data */
CompressedPixelStorage storage() const { return _storage; }
/** /**
* @brief Storage of compressed pixel data * @brief Format of compressed pixel data
* *
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} * Returns either a defined value from the @ref CompressedPixelFormat
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * enum or a wrapped implementation-specific value. Use
* WebGL. * @ref isCompressedPixelFormatImplementationSpecific() to distinguish
* the case and @ref compressedPixelFormatUnwrap() to extract an
* implementation-specific value, if needed.
*/ */
CompressedPixelStorage storage() const { return _storage; } CompressedPixelFormat format() const { return _format; }
#endif
/** @brief Format of compressed pixel data */
GL::CompressedPixelFormat format() const { return _format; }
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<dimensions, Int> size() const { return _size; } VectorTypeFor<dimensions, Int> size() const { return _size; }
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Compressed image data properties * @brief Compressed image data properties
* *
* See @ref CompressedPixelStorage::dataProperties() for more * See @ref CompressedPixelStorage::dataProperties() for more
* information. * information.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this); return Implementation::compressedImageDataProperties<dimensions>(*this);
} }
#endif
/** /**
* @brief Raw data * @brief Raw data
@ -354,8 +587,7 @@ template<UnsignedInt dimensions> class CompressedImage {
return reinterpret_cast<const T*>(_data.data()); return reinterpret_cast<const T*>(_data.data());
} }
#ifdef MAGNUM_BUILD_DEPRECATED #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Set image data * @brief Set image data
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
@ -365,17 +597,12 @@ template<UnsignedInt dimensions> class CompressedImage {
* *
* @deprecated Move-assign a new instance instead. * @deprecated Move-assign a new instance instead.
* *
* Deletes previous data and replaces them with new. Note that the * Deletes previous data and replaces it with @p data.
* data are not copied, but they are deleted on destruction.
* @see @ref release() * @see @ref release()
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
CORRADE_DEPRECATED("move-assign a new instance instead") void setData(CompressedPixelStorage storage, GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) { CORRADE_DEPRECATED("move-assign a new instance instead") void setData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) {
*this = CompressedImage<dimensions>{storage, format, size, std::move(data)}; *this = CompressedImage<dimensions>{storage, GL::CompressedPixelFormat(format), size, std::move(data)};
} }
#endif
/** /**
* @brief Set image data * @brief Set image data
@ -385,28 +612,30 @@ template<UnsignedInt dimensions> class CompressedImage {
* *
* @deprecated Move-assign a new instance instead. * @deprecated Move-assign a new instance instead.
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref setData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/ */
CORRADE_DEPRECATED("move-assign a new instance instead") void setData(GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) { CORRADE_DEPRECATED("move-assign a new instance instead") void setData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) {
*this = CompressedImage<dimensions>{format, size, std::move(data)}; *this = CompressedImage<dimensions>{GL::CompressedPixelFormat(format), size, std::move(data)};
} }
#endif #endif
/** /**
* @brief Release data storage * @brief Release data storage
* *
* Releases the ownership of the data array and resets internal state * Releases the ownership of the data array and resets @ref size() to
* to default. * zero. The state afterwards is equivalent to moved-from state.
* @see @ref setData() * @see @ref data()
*/ */
Containers::Array<char> release(); Containers::Array<char> release();
private: private:
#ifndef MAGNUM_TARGET_GLES /* To be made public once block size and block data size are stored
together with the image */
explicit CompressedImage(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept;
CompressedPixelStorage _storage; CompressedPixelStorage _storage;
#endif CompressedPixelFormat _format;
GL::CompressedPixelFormat _format;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
Containers::Array<char> _data; Containers::Array<char> _data;
}; };
@ -420,15 +649,11 @@ typedef CompressedImage<2> CompressedImage2D;
/** @brief Three-dimensional compressed image */ /** @brief Three-dimensional compressed image */
typedef CompressedImage<3> CompressedImage3D; typedef CompressedImage<3> CompressedImage3D;
template<UnsignedInt dimensions> inline Image<dimensions>::Image(Image<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _type{std::move(other._type)}, _size{std::move(other._size)}, _data{std::move(other._data)} { template<UnsignedInt dimensions> inline Image<dimensions>::Image(Image<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _formatExtra{std::move(other._formatExtra)}, _pixelSize{std::move(other._pixelSize)}, _size{std::move(other._size)}, _data{std::move(other._data)} {
other._size = {}; other._size = {};
} }
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::CompressedImage(CompressedImage<dimensions>&& other) noexcept: template<UnsignedInt dimensions> inline CompressedImage<dimensions>::CompressedImage(CompressedImage<dimensions>&& other) noexcept: _storage{std::move(other._storage)}, _format{std::move(other._format)}, _size{std::move(other._size)}, _data{std::move(other._data)}
#ifndef MAGNUM_TARGET_GLES
_storage{std::move(other._storage)},
#endif
_format{std::move(other._format)}, _size{std::move(other._size)}, _data{std::move(other._data)}
{ {
other._size = {}; other._size = {};
} }
@ -437,7 +662,8 @@ template<UnsignedInt dimensions> inline Image<dimensions>& Image<dimensions>::op
using std::swap; using std::swap;
swap(_storage, other._storage); swap(_storage, other._storage);
swap(_format, other._format); swap(_format, other._format);
swap(_type, other._type); swap(_formatExtra, other._formatExtra);
swap(_pixelSize, other._pixelSize);
swap(_size, other._size); swap(_size, other._size);
swap(_data, other._data); swap(_data, other._data);
return *this; return *this;
@ -445,9 +671,7 @@ template<UnsignedInt dimensions> inline Image<dimensions>& Image<dimensions>::op
template<UnsignedInt dimensions> inline CompressedImage<dimensions>& CompressedImage<dimensions>::operator=(CompressedImage<dimensions>&& other) noexcept { template<UnsignedInt dimensions> inline CompressedImage<dimensions>& CompressedImage<dimensions>::operator=(CompressedImage<dimensions>&& other) noexcept {
using std::swap; using std::swap;
#ifndef MAGNUM_TARGET_GLES
swap(_storage, other._storage); swap(_storage, other._storage);
#endif
swap(_format, other._format); swap(_format, other._format);
swap(_size, other._size); swap(_size, other._size);
swap(_data, other._data); swap(_data, other._data);
@ -456,16 +680,12 @@ template<UnsignedInt dimensions> inline CompressedImage<dimensions>& CompressedI
template<UnsignedInt dimensions> inline Image<dimensions>::operator ImageView<dimensions>() const template<UnsignedInt dimensions> inline Image<dimensions>::operator ImageView<dimensions>() const
{ {
return ImageView<dimensions>{_storage, _format, _type, _size, _data}; return ImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
} }
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::operator CompressedImageView<dimensions>() const template<UnsignedInt dimensions> inline CompressedImage<dimensions>::operator CompressedImageView<dimensions>() const
{ {
return CompressedImageView<dimensions>{ return CompressedImageView<dimensions>{_storage, _format, _size, _data};
#ifndef MAGNUM_TARGET_GLES
_storage,
#endif
_format, _size, _data};
} }
template<UnsignedInt dimensions> inline Containers::Array<char> Image<dimensions>::release() { template<UnsignedInt dimensions> inline Containers::Array<char> Image<dimensions>::release() {
@ -480,31 +700,42 @@ template<UnsignedInt dimensions> inline Containers::Array<char> CompressedImage<
return data; return data;
} }
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::CompressedImage( template<UnsignedInt dimensions> template<class T, class U> inline Image<dimensions>::Image(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage,
#ifndef MAGNUM_TARGET_GLES #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
const CompressedPixelStorage storage, Implementation::wrapPixelFormatIfNotGLSpecific(format),
#else
UnsignedInt(format),
#endif #endif
const GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data): UnsignedInt(formatExtra), Implementation::pixelSizeAdl(format, formatExtra), size, std::move(data)} {
#ifndef MAGNUM_TARGET_GLES static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
_storage{storage}, "format types larger than 32bits are not supported");
#endif }
_format{format}, _size{size}, _data{std::move(data)} {}
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::CompressedImage( template<UnsignedInt dimensions> template<class T> inline Image<dimensions>::Image(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: Image{storage, UnsignedInt(format), {}, Implementation::pixelSizeAdl(format), size, std::move(data)} {
#ifndef MAGNUM_TARGET_GLES static_assert(sizeof(T) <= 4,
const CompressedPixelStorage storage "format types larger than 32bits are not supported");
#endif }
)
#ifndef MAGNUM_TARGET_GLES template<UnsignedInt dimensions> template<class T, class U> inline Image<dimensions>::Image(const PixelStorage storage, const T format, const U formatExtra) noexcept: Image{storage,
: _storage{storage} #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
Implementation::wrapPixelFormatIfNotGLSpecific(format),
#else
UnsignedInt(format),
#endif #endif
{} UnsignedInt(formatExtra), Implementation::pixelSizeAdl(format, formatExtra)} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
#ifndef MAGNUM_TARGET_GLES template<UnsignedInt dimensions> template<class T> inline Image<dimensions>::Image(const PixelStorage storage, const T format) noexcept: Image{storage, UnsignedInt(format), {}, Implementation::pixelSizeAdl(format)} {
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::CompressedImage(const GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data): CompressedImage{{}, format, size, std::move(data)} {} static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> inline CompressedImage<dimensions>::CompressedImage(): CompressedImage{CompressedPixelStorage{}} {} template<UnsignedInt dimensions> template<class T> inline CompressedImage<dimensions>::CompressedImage(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data) noexcept: CompressedImage{storage, UnsignedInt(format), size, std::move(data)} {
#endif static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
} }

26
src/Magnum/ImageView.cpp

@ -25,21 +25,45 @@
#include "ImageView.h" #include "ImageView.h"
#include "Magnum/PixelFormat.h"
namespace Magnum { namespace Magnum {
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(PixelStorage storage, GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: _storage{storage}, _format{format}, _type{type}, _size{size}, _data{reinterpret_cast<const char*>(data.data()), data.size()} { template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: ImageView{storage, format, {}, Magnum::pixelSize(format), size, data} {}
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, data} {}
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{reinterpret_cast<const char*>(data.data()), data.size()} {
CORRADE_ASSERT(!_data || Implementation::imageDataSize(*this) <= _data.size(), "ImageView::ImageView(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); CORRADE_ASSERT(!_data || Implementation::imageDataSize(*this) <= _data.size(), "ImageView::ImageView(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), );
} }
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, format, {}, Magnum::pixelSize(format), size} {}
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size} {}
template<UnsignedInt dimensions> ImageView<dimensions>::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{nullptr} {}
template<UnsignedInt dimensions> void ImageView<dimensions>::setData(const Containers::ArrayView<const void> data) { template<UnsignedInt dimensions> void ImageView<dimensions>::setData(const Containers::ArrayView<const void> data) {
CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "ImageView::setData(): bad image data size, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "ImageView::setData(): bad image data size, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this), );
_data = {reinterpret_cast<const char*>(data.data()), data.size()}; _data = {reinterpret_cast<const char*>(data.data()), data.size()};
} }
template<UnsignedInt dimensions> CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: _storage{storage}, _format{format}, _size{size}, _data{reinterpret_cast<const char*>(data.data()), data.size()} {}
template<UnsignedInt dimensions> CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: _storage{storage}, _format{format}, _size{size} {}
template<UnsignedInt dimensions> CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size, data} {}
template<UnsignedInt dimensions> CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{storage, compressedPixelFormatWrap(format), size} {}
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
template class MAGNUM_EXPORT ImageView<1>; template class MAGNUM_EXPORT ImageView<1>;
template class MAGNUM_EXPORT ImageView<2>; template class MAGNUM_EXPORT ImageView<2>;
template class MAGNUM_EXPORT ImageView<3>; template class MAGNUM_EXPORT ImageView<3>;
template class MAGNUM_EXPORT CompressedImageView<1>;
template class MAGNUM_EXPORT CompressedImageView<2>;
template class MAGNUM_EXPORT CompressedImageView<3>;
#endif #endif
} }

579
src/Magnum/ImageView.h

@ -33,25 +33,91 @@
#include "Magnum/DimensionTraits.h" #include "Magnum/DimensionTraits.h"
#include "Magnum/PixelStorage.h" #include "Magnum/PixelStorage.h"
#include "Magnum/Math/Vector4.h" #include "Magnum/Math/Vector3.h"
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
#include "Magnum/PixelFormat.h"
#endif
namespace Magnum { namespace Magnum {
/** /**
@brief Image view @brief Image view
Adds information about dimensions, color components and component type to some Non-owning view on multi-dimensional image data together with layout and pixel
data in memory. format description. Unlike @ref Image, this class doesn't take ownership of the
data, so it is targeted for wrapping data that is either stored in
stack/constant memory (and shouldn't be deleted) or is managed by something
else.
This class can act as drop-in replacement for @ref Image or
@ref Trade::ImageData, these two are additionally implicitly convertible to it.
Particular graphics API wrappers provide additional image classes, for example
@ref GL::BufferImage. See also @ref CompressedImageView for equivalent
functionality targeted on compressed image formats.
@section ImageView-usage Basic usage
Usually, the view is created on some pre-existing data array in order to
describe its layout, with pixel format being one of the values from the generic
@link PixelFormat @endlink:
@snippet Magnum.cpp ImageView-usage
On construction, the image view internally calculates pixel size corresponding
to given pixel format using @ref pixelSize(). This value is needed to check
that the passed data array is large enough and is also required by most image
manipulation operations.
It's also possible to create an empty view and assign the memory later. That is
useful for example in case of multi-buffered video streaming, where each frame
has the same properties but a different memory location:
@snippet Magnum.cpp ImageView-usage-streaming
It's possible to have views on image sub-rectangles, 3D texture slices or
images with over-aligned rows by passing a particular @ref PixelStorage as
first parameter. In the following snippet, the view is the center 25x25
sub-rectangle of a 75x75 8-bit RGB image , with rows aligned to four bytes:
@snippet Magnum.cpp ImageView-usage-storage
@subsection ImageView-usage-implementation-specific Implementation-specific formats
Unlike @ref Image, this class doesn't delete the data on destruction, so it is For known graphics APIs, there's a set of utility functions converting from
targeted for wrapping data which are either stored in stack/constant memory @ref PixelFormat to implementation-specific format identifiers and such
(and shouldn't be deleted) or they are managed by someone else and have the conversion is done implicitly when passing the view to a particular API. See
same properties for each frame, such as video stream. Thus it is not possible the enum documentation and documentation of its values for more information.
to change image properties, only data pointer.
Interchangeable with @ref Image, @ref BufferImage or @ref Trade::ImageData. In some cases, for example when there's no corresponding generic format
@see @ref ImageView1D, @ref ImageView2D, @ref ImageView3D, available, it's desirable to specify the pixel format using
@ref CompressedImageView implementation-specific identifiers directly. In case of OpenGL that would be
the @ref GL::PixelFormat and @ref GL::PixelType pair:
@snippet Magnum.cpp ImageView-usage-gl
In such cases, pixel size is calculated using either @cpp pixelSize(T, U) @ce
or @cpp pixelSize(T) @ce that is found using
[ADL](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup), with
@cpp T @ce and @cpp U @ce corresponding to types of passed arguments. The
implementation-specific format is wrapped in @ref PixelFormat using
@ref pixelFormatWrap() and @ref format() returns the wrapped value. In order to
distinguish if the format is wrapped, use @ref isPixelFormatImplementationSpecific()
and then extract the implementation-specific identifier using @ref pixelFormatUnwrap().
For APIs that have an additional format specifier (such as OpenGL), the second
value is stored verbatim in @ref formatExtra():
@snippet Magnum.cpp ImageView-usage-gl-extract
As a final fallback, types for which the @cpp pixelSize() @ce overload is not
available can be specified directly together with pixel size. In particular,
pixel size of @cpp 0 @ce will cause the image to be treated as fully opaque
data, disabling all slicing operations. The following shows a image view using
Metal-specific format identifier:
@snippet Magnum.cpp ImageView-usage-metal
@see @ref ImageView1D, @ref ImageView2D, @ref ImageView3D
*/ */
template<UnsignedInt dimensions> class ImageView { template<UnsignedInt dimensions> class ImageView {
public: public:
@ -63,52 +129,241 @@ template<UnsignedInt dimensions> class ImageView {
* @brief Constructor * @brief Constructor
* @param storage Storage of pixel data * @param storage Storage of pixel data
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
* *
* The data are expected to be of proper size for given @p storage * The @p data array is expected to be of proper size for given
* parameters.
*/
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
/**
* @brief Constructor
* @param format Format of pixel data
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* with default-constructed @ref PixelStorage.
*/
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: ImageView{{}, format, size, data} {}
/**
* @brief Construct an empty view
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/
explicit ImageView(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept;
/**
* @brief Construct an empty view
* @param format Format of pixel data
* @param size Image size
*
* Equivalent to calling @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&)
* with default-constructed @ref PixelStorage.
*/
explicit ImageView(PixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, size} {}
/**
* @brief Construct an image view with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param pixelSize Size of a pixel in given format
* @param size Image size
* @param data Image data
*
* Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>),
* where pixel size is calculated automatically using
* @ref pixelSize(PixelFormat), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
* @ref pixelFormatWrap() internally to wrap @p format in
* @ref PixelFormat.
*
* The @p data array is expected to be of proper size for given
* parameters. * parameters.
*/ */
explicit ImageView(PixelStorage storage, GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept; explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
/** @overload /** @overload
* Similar to the above, but uses default @ref PixelStorage parameters. *
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/ */
explicit ImageView(GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: ImageView{{}, format, type, size, data} {} explicit ImageView(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
/** /**
* @brief Constructor * @brief Construct an empty view with implementation-specific pixel format
* @param storage Storage of pixel data * @param storage Storage of pixel data
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data * @param formatExtra Additional pixel format specifier
* @param pixelSize Size of a pixel in given format
* @param size Image size * @param size Image size
* *
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to fill * Unlike with @ref ImageView(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&),
* the image with data. * where pixel size is calculated automatically using
* @ref pixelSize(PixelFormat), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
* @ref pixelFormatWrap() internally to wrap @p format in
* @ref PixelFormat.
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/ */
constexpr explicit ImageView(PixelStorage storage, GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size) noexcept: _storage{storage}, _format{format}, _type{type}, _size{size}, _data{nullptr} {} explicit ImageView(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept;
/** @overload /** @overload
* Similar to the above, but uses default @ref PixelStorage parameters. *
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/
explicit ImageView(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
*
* Uses ADL to find a corresponding @cpp pixelSize(T, U) @ce overload,
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* with calculated pixel size.
*/
template<class T, class U> explicit ImageView(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
*
* Uses ADL to find a corresponding @cpp pixelSize(T) @ce overload,
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/ */
constexpr explicit ImageView(GL::PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, type, size} {} template<class T> explicit ImageView(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
/**
* @brief Construct an image view with implementation-specific pixel format
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref ImageView(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* with default-constructed @ref PixelStorage.
*/
template<class T, class U> explicit ImageView(T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: ImageView{{}, format, formatExtra, size, data} {}
/**
* @brief Construct an image view with implementation-specific pixel format
* @param format Format of pixel data
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref ImageView(PixelStorage, T, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* with default-constructed @ref PixelStorage.
*/
template<class T> explicit ImageView(T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: ImageView{{}, format, size, data} {}
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
*
* Uses ADL to find a corresponding @cpp pixelSize(T, U) @ce overload,
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&)
* with calculated pixel size.
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/
template<class T, class U> explicit ImageView(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
*
* Uses ADL to find a corresponding @cpp pixelSize(T) @ce overload,
* then calls @ref ImageView(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* assign a memory view to the image.
*/
template<class T> explicit ImageView(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size) noexcept;
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
*
* Equivalent to calling @ref ImageView(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* with default-constructed @ref PixelStorage.
*/
template<class T, class U> explicit ImageView(T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, formatExtra, size} {}
/**
* @brief Construct an empty view with implementation-specific pixel format
* @param format Format of pixel data
* @param size Image size
*
* Equivalent to calling @ref ImageView(PixelStorage, T, const VectorTypeFor<dimensions, Int>&)
* with default-constructed @ref PixelStorage.
*/
template<class T> explicit ImageView(T format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, size} {}
/** @brief Storage of pixel data */ /** @brief Storage of pixel data */
PixelStorage storage() const { return _storage; } PixelStorage storage() const { return _storage; }
/** @brief Format of pixel data */ /**
GL::PixelFormat format() const { return _format; } * @brief Format of pixel data
*
* Returns either a defined value from the @ref PixelFormat enum or a
* wrapped implementation-specific value. Use
* @ref isPixelFormatImplementationSpecific() to distinguish the case
* and @ref pixelFormatUnwrap() to extract an implementation-specific
* value, if needed.
* @see @ref formatExtra()
*/
PixelFormat format() const { return _format; }
/** @brief Data type of pixel data */ /**
GL::PixelType type() const { return _type; } * @brief Additional pixel format specifier
*
* Some implementations (such as OpenGL) define a pixel format using
* two values. This field contains the second implementation-specific
* value verbatim, if any. See @ref format() for more information.
*/
UnsignedInt formatExtra() const { return _formatExtra; }
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Data type of pixel data
* @deprecated Cast @ref formatExtra() to @ref GL::PixelType instead.
*/
CORRADE_DEPRECATED("cast formatExtra() to GL::PixelType instead") GL::PixelType type() const { return GL::PixelType(_formatExtra); }
#endif
/** /**
* @brief Pixel size (in bytes) * @brief Pixel size (in bytes)
* *
* @see @ref PixelStorage::pixelSize() * @see @ref pixelSize(PixelFormat)
*/ */
std::size_t pixelSize() const { return PixelStorage::pixelSize(_format, _type); } UnsignedInt pixelSize() const { return _pixelSize; }
/** @brief Image size */ /** @brief Image size */
constexpr VectorTypeFor<dimensions, Int> size() const { return _size; } constexpr VectorTypeFor<dimensions, Int> size() const { return _size; }
@ -122,8 +377,8 @@ template<UnsignedInt dimensions> class ImageView {
return Implementation::imageDataProperties<dimensions>(*this); return Implementation::imageDataProperties<dimensions>(*this);
} }
/** @brief Raw data */ /** @brief Image data */
constexpr Containers::ArrayView<const char> data() const { return _data; } Containers::ArrayView<const char> data() const { return _data; }
/** @overload */ /** @overload */
template<class T> const T* data() const { template<class T> const T* data() const {
@ -132,18 +387,17 @@ template<UnsignedInt dimensions> class ImageView {
/** /**
* @brief Set image data * @brief Set image data
* @param data Image data
* *
* Storage parameters, pixel format, type and size remain the same as * The data array is expected to be of proper size for parameters
* passed in constructor. The data are expected to be of proper size * specified in the constructor.
* for given @p storage parameters.
*/ */
void setData(Containers::ArrayView<const void> data); void setData(Containers::ArrayView<const void> data);
private: private:
PixelStorage _storage; PixelStorage _storage;
GL::PixelFormat _format; PixelFormat _format;
GL::PixelType _type; UnsignedInt _formatExtra;
UnsignedInt _pixelSize;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
Containers::ArrayView<const char> _data; Containers::ArrayView<const char> _data;
}; };
@ -160,10 +414,63 @@ typedef ImageView<3> ImageView3D;
/** /**
@brief Compressed image view @brief Compressed image view
Adds information about dimensions and compression type to some data in memory. Non-owning view on multi-dimensional compressed image data together with layout
and compressed block format description. Unlike @ref CompressedImage, this
class doesn't take ownership of the data, so it is targeted for wrapping data
that is either stored in stack/constant memory (and shouldn't be deleted) or is
managed by something else.
This class can act as drop-in replacement for @ref CompressedImage or
@ref Trade::ImageData, these two are additionally implicitly convertible to it.
Particular graphics API wrappers provide additional image classes, for example
@ref GL::CompressedBufferImage. See also @ref ImageView for equivalent
functionality targeted on non-compressed image formats.
@section CompressedImageView-usage Basic usage
Usually, the view is created on some pre-existing data array in order to
describe its layout, with pixel format being one of the values from the generic
@link CompressedPixelFormat @endlink:
@snippet Magnum.cpp CompressedImageView-usage
It's also possible to create an empty view and assign the memory later. That is
useful for example in case of multi-buffered video streaming, where each frame
has the same properties but a different memory location:
@snippet Magnum.cpp CompressedImageView-usage-streaming
It's possible to have views on image sub-rectangles, 3D texture slices or
images with over-aligned rows by passing a particular @ref CompressedPixelStorage
as first parameter. In the following snippet, the view is the bottom-right
32x32 sub-rectangle of a 64x64 image:
@snippet Magnum.cpp CompressedImageView-usage-storage
@subsection CompressedImageView-usage-implementation-specific Implementation-specific formats
For known graphics APIs, there's a set of utility functions converting from
@ref CompressedPixelFormat to implementation-specific format identifiers and
such conversion is done implicitly when passing the view to a particular API.
See the enum documentation and documentation of its values for more
information.
In some cases, for example when there's no corresponding generic format
available, it's desirable to specify the pixel format using
implementation-specific identifiers directly. In case of OpenGL that would be
@link GL::CompressedPixelFormat @endlink:
@snippet Magnum.cpp CompressedImageView-usage-gl
In such cases, the implementation-specific format is wrapped in
@ref CompressedPixelFormat using @ref compressedPixelFormatWrap() and
@ref format() returns the wrapped value. In order to distinguish if the format
is wrapped, use @ref isCompressedPixelFormatImplementationSpecific() and then
extract the implementation-specific identifier using
@ref compressedPixelFormatUnwrap():
@snippet Magnum.cpp CompressedImageView-usage-gl-extract
See @ref ImageView for more information. Interchangeable with
@ref CompressedImage, @ref CompressedBufferImage or @ref Trade::ImageData.
@see @ref CompressedImageView1D, @ref CompressedImageView2D, @see @ref CompressedImageView1D, @ref CompressedImageView2D,
@ref CompressedImageView3D @ref CompressedImageView3D
*/ */
@ -173,20 +480,14 @@ template<UnsignedInt dimensions> class CompressedImageView {
Dimensions = dimensions /**< Image dimension count */ Dimensions = dimensions /**< Image dimension count */
}; };
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Constructor * @brief Constructor
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data * @param format Format of compressed pixel data
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
*
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
constexpr explicit CompressedImageView(CompressedPixelStorage storage, GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept; explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
#endif
/** /**
* @brief Constructor * @brief Constructor
@ -194,71 +495,107 @@ template<UnsignedInt dimensions> class CompressedImageView {
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/ */
constexpr explicit CompressedImageView(GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept; explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: CompressedImageView{{}, format, size, data} {}
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Constructor * @brief Construct an empty view
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data * @param format Format of compressed pixel data
* @param size Image size * @param size Image size
* *
* Data pointer is set to @cpp nullptr @ce, call @ref setData() to fill * Data pointer is set to @cpp nullptr @ce, call @ref setData() to
* the image with data. * assign a memory view to the image.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
constexpr explicit CompressedImageView(CompressedPixelStorage storage, GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept; explicit CompressedImageView(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept;
#endif
/** /**
* @brief Constructor * @brief Construct an empty view
* @param format Format of compressed pixel data * @param format Format of compressed pixel data
* @param size Image size * @param size Image size
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/ */
constexpr explicit CompressedImageView(GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept; explicit CompressedImageView(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {}
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Storage of compressed pixel data * @brief Construct an image view with implementation-specific format
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat.
*/
template<class T> explicit CompressedImageView(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
/**
* @brief Construct an image view with implementation-specific format
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
*
* Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::ArrayView<const void>)
* with default-constructed @ref CompressedPixelStorage.
*/
template<class T> explicit CompressedImageView(T format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept: CompressedImageView{{}, format, size, data} {}
/**
* @brief Construct an empty view with implementation-specific format
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat. Data pointer is set to
* @cpp nullptr @ce, call @ref setData() to assign a memory view to the
* image.
*/
template<class T> explicit CompressedImageView(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size) noexcept;
/**
* @brief Construct an empty view with implementation-specific format
* @param format Format of compressed pixel data
* @param size Image size
* *
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} * Equivalent to calling @ref CompressedImageView(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&)
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and * with default-constructed @ref CompressedPixelStorage.
* WebGL.
*/ */
template<class T> explicit CompressedImageView(T format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {}
/** @brief Storage of compressed pixel data */
CompressedPixelStorage storage() const { return _storage; } CompressedPixelStorage storage() const { return _storage; }
#endif
/** @brief Format of compressed data */ /**
GL::CompressedPixelFormat format() const { return _format; } * @brief Format of compressed pixel data
*
* Returns either a defined value from the @ref CompressedPixelFormat
* enum or a wrapped implementation-specific value. Use
* @ref isCompressedPixelFormatImplementationSpecific() to distinguish
* the case and @ref compressedPixelFormatUnwrap() to extract an
* implementation-specific value, if needed.
*/
CompressedPixelFormat format() const { return _format; }
/** @brief Image size */ /** @brief Image size */
constexpr VectorTypeFor<dimensions, Int> size() const { return _size; } constexpr VectorTypeFor<dimensions, Int> size() const { return _size; }
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Compressed image data properties * @brief Compressed image data properties
* *
* See @ref CompressedPixelStorage::dataProperties() for more * See @ref CompressedPixelStorage::dataProperties() for more
* information. * information.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const { std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> dataProperties() const {
return Implementation::compressedImageDataProperties<dimensions>(*this); return Implementation::compressedImageDataProperties<dimensions>(*this);
} }
#endif
/** @brief Raw data */ /** @brief Image data */
constexpr Containers::ArrayView<const char> data() const { return _data; } Containers::ArrayView<const char> data() const { return _data; }
/** @overload */ /** @overload */
template<class T> const T* data() const { template<class T> const T* data() const {
@ -267,21 +604,22 @@ template<UnsignedInt dimensions> class CompressedImageView {
/** /**
* @brief Set image data * @brief Set image data
* @param data Image data
* *
* Dimensions, color compnents and data type remains the same as * The data array is expected to be of proper size for parameters
* passed in constructor. The data are not copied nor deleted on * specified in the constructor.
* destruction.
*/ */
void setData(Containers::ArrayView<const void> data) { void setData(Containers::ArrayView<const void> data) {
_data = {reinterpret_cast<const char*>(data.data()), data.size()}; _data = {reinterpret_cast<const char*>(data.data()), data.size()};
} }
private: private:
#ifndef MAGNUM_TARGET_GLES /* To be made public once block size and block data size are stored
together with the image */
explicit CompressedImageView(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::ArrayView<const void> data) noexcept;
explicit CompressedImageView(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size) noexcept;
CompressedPixelStorage _storage; CompressedPixelStorage _storage;
#endif CompressedPixelFormat _format;
GL::CompressedPixelFormat _format;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
Containers::ArrayView<const char> _data; Containers::ArrayView<const char> _data;
}; };
@ -295,31 +633,62 @@ typedef CompressedImageView<2> CompressedImageView2D;
/** @brief Three-dimensional compressed image view */ /** @brief Three-dimensional compressed image view */
typedef CompressedImageView<3> CompressedImageView3D; typedef CompressedImageView<3> CompressedImageView3D;
template<UnsignedInt dimensions> constexpr CompressedImageView<dimensions>::CompressedImageView( namespace Implementation {
#ifndef MAGNUM_TARGET_GLES template<class T> inline UnsignedInt pixelSizeAdl(T format) {
const CompressedPixelStorage storage, return pixelSize(format);
#endif }
const GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept:
#ifndef MAGNUM_TARGET_GLES template<class T, class U> inline UnsignedInt pixelSizeAdl(T format, U formatExtra) {
_storage{storage}, /* So it doesn't warn when the deprecated
#endif pixelSize(PixelFormat, GL::PixelType) overload is called
_format{format}, _size{size}, _data{reinterpret_cast<const char*>(data.data()), data.size()} {} indirectly */
CORRADE_IGNORE_DEPRECATED_PUSH
return pixelSize(format, formatExtra);
CORRADE_IGNORE_DEPRECATED_POP
}
}
template<UnsignedInt dimensions> constexpr CompressedImageView<dimensions>::CompressedImageView( template<UnsignedInt dimensions> template<class T, class U> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: ImageView{storage,
#ifndef MAGNUM_TARGET_GLES #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
const CompressedPixelStorage storage, Implementation::wrapPixelFormatIfNotGLSpecific(format),
#else
UnsignedInt(format),
#endif #endif
const GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: UnsignedInt(formatExtra), Implementation::pixelSizeAdl(format, formatExtra), size, data} {
#ifndef MAGNUM_TARGET_GLES static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
_storage{storage}, "format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelSizeAdl(format), size, data} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T, class U> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage,
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
Implementation::wrapPixelFormatIfNotGLSpecific(format),
#else
UnsignedInt(format),
#endif #endif
_format{format}, _size{size} {} UnsignedInt(formatExtra), Implementation::pixelSizeAdl(format, formatExtra), size} {
static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
"format types larger than 32bits are not supported");
}
#ifndef MAGNUM_TARGET_GLES template<UnsignedInt dimensions> template<class T> inline ImageView<dimensions>::ImageView(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{storage, UnsignedInt(format), {}, Implementation::pixelSizeAdl(format), size} {
template<UnsignedInt dimensions> constexpr CompressedImageView<dimensions>::CompressedImageView(const GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: CompressedImageView{{}, format, size, data} {} static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> constexpr CompressedImageView<dimensions>::CompressedImageView(const GL::CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {} template<UnsignedInt dimensions> template<class T> inline CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<const void> data) noexcept: CompressedImageView{storage, UnsignedInt(format), size, data} {
#endif static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> inline CompressedImageView<dimensions>::CompressedImageView(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{storage, UnsignedInt(format), size} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
} }

7
src/Magnum/Magnum.h

@ -698,10 +698,11 @@ typedef CompressedImageView<1> CompressedImageView1D;
typedef CompressedImageView<2> CompressedImageView2D; typedef CompressedImageView<2> CompressedImageView2D;
typedef CompressedImageView<3> CompressedImageView3D; typedef CompressedImageView<3> CompressedImageView3D;
enum class PixelFormat: UnsignedInt;
enum class CompressedPixelFormat: UnsignedInt;
class PixelStorage; class PixelStorage;
#ifndef MAGNUM_TARGET_GLES
class CompressedPixelStorage; class CompressedPixelStorage;
#endif
enum class ResourceState: UnsignedByte; enum class ResourceState: UnsignedByte;
enum class ResourceDataState: UnsignedByte; enum class ResourceDataState: UnsignedByte;
@ -771,9 +772,7 @@ typedef CORRADE_DEPRECATED("use GL::MultisampleTexture2D instead") GL::Multisamp
typedef CORRADE_DEPRECATED("use GL::MultisampleTexture2DArray instead") GL::MultisampleTexture2DArray MultisampleTexture2DArray; typedef CORRADE_DEPRECATED("use GL::MultisampleTexture2DArray instead") GL::MultisampleTexture2DArray MultisampleTexture2DArray;
#endif #endif
typedef CORRADE_DEPRECATED("use GL::PixelFormat instead") GL::PixelFormat PixelFormat;
typedef CORRADE_DEPRECATED("use GL::PixelType instead") GL::PixelType PixelType; typedef CORRADE_DEPRECATED("use GL::PixelType instead") GL::PixelType PixelType;
typedef CORRADE_DEPRECATED("use GL::CompressedPixelFormat instead") GL::CompressedPixelFormat CompressedPixelFormat;
typedef CORRADE_DEPRECATED("use GL::PrimitiveQuery instead") GL::PrimitiveQuery PrimitiveQuery; typedef CORRADE_DEPRECATED("use GL::PrimitiveQuery instead") GL::PrimitiveQuery PrimitiveQuery;
typedef CORRADE_DEPRECATED("use GL::SampleQuery instead") GL::SampleQuery SampleQuery; typedef CORRADE_DEPRECATED("use GL::SampleQuery instead") GL::SampleQuery SampleQuery;

369
src/Magnum/PixelFormat.cpp

@ -0,0 +1,369 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/PixelFormat.h"
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Debug.h>
namespace Magnum {
UnsignedInt pixelSize(const PixelFormat format) {
CORRADE_ASSERT(!(UnsignedInt(format) & (1 << 31)),
"pixelSize(): can't determine pixel size of an implementation-specific format", {});
switch(format) {
case PixelFormat::R8Unorm:
case PixelFormat::R8Snorm:
case PixelFormat::R8UI:
case PixelFormat::R8I:
return 1;
case PixelFormat::RG8Unorm:
case PixelFormat::RG8Snorm:
case PixelFormat::RG8UI:
case PixelFormat::RG8I:
case PixelFormat::R16Unorm:
case PixelFormat::R16Snorm:
case PixelFormat::R16UI:
case PixelFormat::R16I:
case PixelFormat::R16F:
return 2;
case PixelFormat::RGB8Unorm:
case PixelFormat::RGB8Snorm:
case PixelFormat::RGB8UI:
case PixelFormat::RGB8I:
return 3;
case PixelFormat::RGBA8Unorm:
case PixelFormat::RGBA8Snorm:
case PixelFormat::RGBA8UI:
case PixelFormat::RGBA8I:
case PixelFormat::RG16Unorm:
case PixelFormat::RG16Snorm:
case PixelFormat::RG16UI:
case PixelFormat::RG16I:
case PixelFormat::RG16F:
case PixelFormat::R32UI:
case PixelFormat::R32I:
case PixelFormat::R32F:
return 4;
case PixelFormat::RGB16Unorm:
case PixelFormat::RGB16Snorm:
case PixelFormat::RGB16UI:
case PixelFormat::RGB16I:
case PixelFormat::RGB16F:
return 6;
case PixelFormat::RGBA16Unorm:
case PixelFormat::RGBA16Snorm:
case PixelFormat::RGBA16UI:
case PixelFormat::RGBA16I:
case PixelFormat::RGBA16F:
case PixelFormat::RG32UI:
case PixelFormat::RG32I:
case PixelFormat::RG32F:
return 8;
case PixelFormat::RGB32UI:
case PixelFormat::RGB32I:
case PixelFormat::RGB32F:
return 12;
case PixelFormat::RGBA32UI:
case PixelFormat::RGBA32I:
case PixelFormat::RGBA32F:
return 16;
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
CORRADE_IGNORE_DEPRECATED_PUSH
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
case PixelFormat::Red:
#endif
#ifndef MAGNUM_TARGET_GLES
case PixelFormat::Green:
case PixelFormat::Blue:
#endif
#ifdef MAGNUM_TARGET_GLES2
case PixelFormat::Luminance:
#endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
case PixelFormat::RG:
#endif
#ifdef MAGNUM_TARGET_GLES2
case PixelFormat::LuminanceAlpha:
#endif
case PixelFormat::RGB:
case PixelFormat::RGBA:
#ifndef MAGNUM_TARGET_GLES
case PixelFormat::BGR:
#endif
#ifndef MAGNUM_TARGET_WEBGL
case PixelFormat::BGRA:
#endif
#ifdef MAGNUM_TARGET_GLES2
case PixelFormat::SRGB:
case PixelFormat::SRGBAlpha:
#endif
#ifndef MAGNUM_TARGET_GLES2
case PixelFormat::RedInteger:
#ifndef MAGNUM_TARGET_GLES
case PixelFormat::GreenInteger:
case PixelFormat::BlueInteger:
#endif
case PixelFormat::RGInteger:
case PixelFormat::RGBInteger:
case PixelFormat::RGBAInteger:
#ifndef MAGNUM_TARGET_GLES
case PixelFormat::BGRInteger:
case PixelFormat::BGRAInteger:
#endif
#endif
case PixelFormat::DepthComponent:
#ifndef MAGNUM_TARGET_WEBGL
case PixelFormat::StencilIndex:
#endif
case PixelFormat::DepthStencil:
/** @todo CORRADE_ASSERT_UNREACHABLE() with message here */
CORRADE_ASSERT(false,
"pixelSize(): called with deprecated GL-specific format, use GL::pixelSize() instead", {});
CORRADE_IGNORE_DEPRECATED_POP
#endif
}
CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug& operator<<(Debug& debug, const PixelFormat value) {
if(isPixelFormatImplementationSpecific(value)) {
return debug << "PixelFormat::ImplementationSpecific(" << Debug::nospace << reinterpret_cast<void*>(pixelFormatUnwrap(value)) << Debug::nospace << ")";
}
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case PixelFormat::value: return debug << "PixelFormat::" #value;
_c(R8Unorm)
_c(RG8Unorm)
_c(RGB8Unorm)
_c(RGBA8Unorm)
_c(R8Snorm)
_c(RG8Snorm)
_c(RGB8Snorm)
_c(RGBA8Snorm)
_c(R8UI)
_c(RG8UI)
_c(RGB8UI)
_c(RGBA8UI)
_c(R8I)
_c(RG8I)
_c(RGB8I)
_c(RGBA8I)
_c(R16Unorm)
_c(RG16Unorm)
_c(RGB16Unorm)
_c(RGBA16Unorm)
_c(R16Snorm)
_c(RG16Snorm)
_c(RGB16Snorm)
_c(RGBA16Snorm)
_c(R16UI)
_c(RG16UI)
_c(RGB16UI)
_c(RGBA16UI)
_c(R16I)
_c(RG16I)
_c(RGB16I)
_c(RGBA16I)
_c(R32UI)
_c(RG32UI)
_c(RGB32UI)
_c(RGBA32UI)
_c(R32I)
_c(RG32I)
_c(RGB32I)
_c(RGBA32I)
_c(R16F)
_c(RG16F)
_c(RGB16F)
_c(RGBA16F)
_c(R32F)
_c(RG32F)
_c(RGB32F)
_c(RGBA32F)
#undef _c
/* Verbatim copy from GL/PixelFormat.cpp. Here mainly to suppress
compiler warnings about unhandled cases, to check that all values
from the original enum are present and also to check that there are
no accidentally conflicting values. */
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
CORRADE_IGNORE_DEPRECATED_PUSH
#define _c(value) case PixelFormat::value: return debug << "GL::PixelFormat::" #value;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
_c(Red)
#endif
#ifndef MAGNUM_TARGET_GLES
_c(Green)
_c(Blue)
#endif
#ifdef MAGNUM_TARGET_GLES2
_c(Luminance)
#endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
_c(RG)
#endif
#ifdef MAGNUM_TARGET_GLES2
_c(LuminanceAlpha)
#endif
_c(RGB)
_c(RGBA)
#ifndef MAGNUM_TARGET_GLES
_c(BGR)
#endif
#ifndef MAGNUM_TARGET_WEBGL
_c(BGRA)
#endif
#ifdef MAGNUM_TARGET_GLES2
_c(SRGB)
_c(SRGBAlpha)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(RedInteger)
#ifndef MAGNUM_TARGET_GLES
_c(GreenInteger)
_c(BlueInteger)
#endif
_c(RGInteger)
_c(RGBInteger)
_c(RGBAInteger)
#ifndef MAGNUM_TARGET_GLES
_c(BGRInteger)
_c(BGRAInteger)
#endif
#endif
_c(DepthComponent)
#ifndef MAGNUM_TARGET_WEBGL
_c(StencilIndex)
#endif
_c(DepthStencil)
#undef _c
CORRADE_IGNORE_DEPRECATED_POP
#endif
/* LCOV_EXCL_STOP */
}
return debug << "PixelFormat(" << Debug::nospace << reinterpret_cast<void*>(UnsignedInt(value)) << Debug::nospace << ")";
}
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug& operator<<(Debug& debug, const CompressedPixelFormat value) {
if(isCompressedPixelFormatImplementationSpecific(value)) {
return debug << "CompressedPixelFormat::ImplementationSpecific(" << Debug::nospace << reinterpret_cast<void*>(compressedPixelFormatUnwrap(value)) << Debug::nospace << ")";
}
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case CompressedPixelFormat::value: return debug << "CompressedPixelFormat::" #value;
_c(Bc1RGBUnorm)
_c(Bc1RGBAUnorm)
_c(Bc2RGBAUnorm)
_c(Bc3RGBAUnorm)
#undef _c
/* Verbatim copy from GL/PixelFormat.cpp. Here mainly to suppress
compiler warnings about unhandled cases, to check that all values
from the original enum are present and also to check that there are
no accidentally conflicting values. */
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
CORRADE_IGNORE_DEPRECATED_PUSH
#define _c(value) case CompressedPixelFormat::value: return debug << "GL::CompressedPixelFormat::" #value;
#ifndef MAGNUM_TARGET_GLES
_c(Red)
_c(RG)
_c(RGB)
_c(RGBA)
_c(RedRgtc1)
_c(RGRgtc2)
_c(SignedRedRgtc1)
_c(SignedRGRgtc2)
_c(RGBBptcUnsignedFloat)
_c(RGBBptcSignedFloat)
_c(RGBABptcUnorm)
_c(SRGBAlphaBptcUnorm)
#endif
#ifndef MAGNUM_TARGET_GLES2
_c(RGB8Etc2)
_c(SRGB8Etc2)
_c(RGB8PunchthroughAlpha1Etc2)
_c(SRGB8PunchthroughAlpha1Etc2)
_c(RGBA8Etc2Eac)
_c(SRGB8Alpha8Etc2Eac)
_c(R11Eac)
_c(SignedR11Eac)
_c(RG11Eac)
_c(SignedRG11Eac)
#endif
_c(RGBS3tcDxt1)
_c(RGBAS3tcDxt1)
_c(RGBAS3tcDxt3)
_c(RGBAS3tcDxt5)
#ifndef MAGNUM_TARGET_WEBGL
_c(RGBAAstc4x4)
_c(SRGB8Alpha8Astc4x4)
_c(RGBAAstc5x4)
_c(SRGB8Alpha8Astc5x4)
_c(RGBAAstc5x5)
_c(SRGB8Alpha8Astc5x5)
_c(RGBAAstc6x5)
_c(SRGB8Alpha8Astc6x5)
_c(RGBAAstc6x6)
_c(SRGB8Alpha8Astc6x6)
_c(RGBAAstc8x5)
_c(SRGB8Alpha8Astc8x5)
_c(RGBAAstc8x6)
_c(SRGB8Alpha8Astc8x6)
_c(RGBAAstc8x8)
_c(SRGB8Alpha8Astc8x8)
_c(RGBAAstc10x5)
_c(SRGB8Alpha8Astc10x5)
_c(RGBAAstc10x6)
_c(SRGB8Alpha8Astc10x6)
_c(RGBAAstc10x8)
_c(SRGB8Alpha8Astc10x8)
_c(RGBAAstc10x10)
_c(SRGB8Alpha8Astc10x10)
_c(RGBAAstc12x10)
_c(SRGB8Alpha8Astc12x10)
_c(RGBAAstc12x12)
_c(SRGB8Alpha8Astc12x12)
#undef _c
#endif
CORRADE_IGNORE_DEPRECATED_POP
#endif
/* LCOV_EXCL_STOP */
}
return debug << "CompressedPixelFormat(" << Debug::nospace << reinterpret_cast<void*>(UnsignedInt(value)) << Debug::nospace << ")";
}
#endif
}

1115
src/Magnum/PixelFormat.h

File diff suppressed because it is too large Load Diff

39
src/Magnum/PixelStorage.h

@ -52,10 +52,21 @@ Descibes how to interpret data which are read from or stored into @ref Image,
class MAGNUM_EXPORT PixelStorage { class MAGNUM_EXPORT PixelStorage {
public: public:
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/** @brief @copybrief GL::pixelSize() /** @brief Pixel size
* @deprecated Use @ref GL::pixelSize() instead. * @deprecated Use @ref Magnum::pixelSize() or @ref GL::pixelSize()
* instead.
*/ */
static CORRADE_DEPRECATED("use GL::pixelSize() instead") std::size_t pixelSize(GL::PixelFormat format, GL::PixelType type); static CORRADE_DEPRECATED("use GL::pixelSize() instead") std::size_t pixelSize(GL::PixelFormat format, GL::PixelType type);
/** @brief Pixel size
* @deprecated Use @ref Magnum::pixelSize() or @ref GL::pixelSize()
* instead.
*/
static CORRADE_DEPRECATED("use GL::pixelSize() instead") std::size_t pixelSize(PixelFormat format, GL::PixelType type) {
CORRADE_IGNORE_DEPRECATED_PUSH
return pixelSize(GL::PixelFormat(format), type);
CORRADE_IGNORE_DEPRECATED_POP
}
#endif #endif
/** /**
@ -153,6 +164,20 @@ class MAGNUM_EXPORT PixelStorage {
* instead. * instead.
*/ */
CORRADE_DEPRECATED("use dataProperties(std::size_t, const Vector3i&) instead") std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t> dataProperties(GL::PixelFormat format, GL::PixelType type, const Vector3i& size) const; CORRADE_DEPRECATED("use dataProperties(std::size_t, const Vector3i&) instead") std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t> dataProperties(GL::PixelFormat format, GL::PixelType type, const Vector3i& size) const;
/** @brief @copybrief dataProperties(std::size_t, const Vector3i&) const
*
* 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.
* @deprecated Use @ref dataProperties(std::size_t, const Vector3i&) const
* instead.
*/
CORRADE_DEPRECATED("use dataProperties(std::size_t, const Vector3i&) instead") std::tuple<Math::Vector3<std::size_t>, Math::Vector3<std::size_t>, std::size_t> dataProperties(PixelFormat format, GL::PixelType type, const Vector3i& size) const {
CORRADE_IGNORE_DEPRECATED_PUSH
return dataProperties(GL::PixelFormat(format), type, size);
CORRADE_IGNORE_DEPRECATED_POP
}
#endif #endif
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -287,9 +312,8 @@ namespace Implementation {
/* Used in *Image::dataProperties() */ /* Used in *Image::dataProperties() */
template<std::size_t dimensions, class T> std::tuple<Math::Vector<dimensions, std::size_t>, Math::Vector<dimensions, std::size_t>, std::size_t> imageDataProperties(const T& image) { template<std::size_t dimensions, class T> std::tuple<Math::Vector<dimensions, std::size_t>, Math::Vector<dimensions, std::size_t>, std::size_t> imageDataProperties(const T& image) {
Math::Vector3<std::size_t> offset, dataSize; Math::Vector3<std::size_t> offset, dataSize;
std::size_t pixelSize; std::tie(offset, dataSize) = image.storage().dataProperties(image.pixelSize(), Vector3i::pad(image.size(), 1));
std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(image.size(), 1)); return std::make_tuple(Math::Vector<dimensions, std::size_t>::pad(offset), Math::Vector<dimensions, std::size_t>::pad(dataSize), image.pixelSize());
return std::make_tuple(Math::Vector<dimensions, std::size_t>::pad(offset), Math::Vector<dimensions, std::size_t>::pad(dataSize), pixelSize);
} }
/* Used in Compressed*Image::dataProperties() */ /* Used in Compressed*Image::dataProperties() */
@ -303,8 +327,7 @@ namespace Implementation {
/* Used in image query functions */ /* Used in image query functions */
template<std::size_t dimensions, class T> std::size_t imageDataSizeFor(const T& image, const Math::Vector<dimensions, Int>& size) { template<std::size_t dimensions, class T> std::size_t imageDataSizeFor(const T& image, const Math::Vector<dimensions, Int>& size) {
Math::Vector3<std::size_t> offset, dataSize; Math::Vector3<std::size_t> offset, dataSize;
std::size_t pixelSize; std::tie(offset, dataSize) = image.storage().dataProperties(image.pixelSize(), Vector3i::pad(size, 1));
std::tie(offset, dataSize, pixelSize) = image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1));
/* Smallest line/rectangle/cube that covers the area */ /* Smallest line/rectangle/cube that covers the area */
std::size_t dataOffset = 0; std::size_t dataOffset = 0;
@ -350,7 +373,7 @@ namespace Implementation {
} }
template<std::size_t dimensions, class T> std::ptrdiff_t pixelStorageSkipOffsetFor(const T& image, const Math::Vector<dimensions, Int>& size) { template<std::size_t dimensions, class T> std::ptrdiff_t pixelStorageSkipOffsetFor(const T& image, const Math::Vector<dimensions, Int>& size) {
return std::get<0>(image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1))).sum(); return std::get<0>(image.storage().dataProperties(image.pixelSize(), Vector3i::pad(size, 1))).sum();
} }
template<class T> std::ptrdiff_t pixelStorageSkipOffset(const T& image) { template<class T> std::ptrdiff_t pixelStorageSkipOffset(const T& image) {
return pixelStorageSkipOffsetFor(image, image.size()); return pixelStorageSkipOffsetFor(image, image.size());

3
src/Magnum/Test/CMakeLists.txt

@ -24,6 +24,8 @@
# #
corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum) corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum)
corrade_add_test(PixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumTestLib)
target_compile_definitions(PixelFormatTest PRIVATE "CORRADE_GRACEFUL_ASSERT")
corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES Magnum) corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES Magnum)
target_compile_definitions(ResourceManagerTest PRIVATE "CORRADE_GRACEFUL_ASSERT") target_compile_definitions(ResourceManagerTest PRIVATE "CORRADE_GRACEFUL_ASSERT")
@ -38,6 +40,7 @@ corrade_add_test(TagsTest TagsTest.cpp LIBRARIES Magnum)
set_target_properties( set_target_properties(
ArrayTest ArrayTest
PixelFormatTest
ResourceManagerTest ResourceManagerTest
ResourceManagerLocalInstanceTestLib ResourceManagerLocalInstanceTestLib
ResourceManagerLocalInstanceTest ResourceManagerLocalInstanceTest

216
src/Magnum/Test/PixelFormatTest.cpp

@ -0,0 +1,216 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/PixelFormat.h"
namespace Magnum { namespace Test {
struct PixelFormatTest: TestSuite::Tester {
explicit PixelFormatTest();
void size();
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void sizeDeprecated();
#endif
void sizeImplementationSpecific();
void isImplementationSpecific();
void wrap();
void wrapInvalid();
void unwrap();
void unwrapInvalid();
void compressedIsImplementationSpecific();
void compressedWrap();
void compressedWrapInvalid();
void compressedUnwrap();
void compressedUnwrapInvalid();
void debug();
void debugImplementationSpecific();
void compressedDebug();
void compressedDebugImplementationSpecific();
};
PixelFormatTest::PixelFormatTest() {
addTests({&PixelFormatTest::size,
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
&PixelFormatTest::sizeDeprecated,
#endif
&PixelFormatTest::sizeImplementationSpecific,
&PixelFormatTest::isImplementationSpecific,
&PixelFormatTest::wrap,
&PixelFormatTest::wrapInvalid,
&PixelFormatTest::unwrap,
&PixelFormatTest::unwrapInvalid,
&PixelFormatTest::compressedIsImplementationSpecific,
&PixelFormatTest::compressedWrap,
&PixelFormatTest::compressedWrapInvalid,
&PixelFormatTest::compressedUnwrap,
&PixelFormatTest::compressedUnwrapInvalid,
&PixelFormatTest::debug,
&PixelFormatTest::debugImplementationSpecific,
&PixelFormatTest::compressedDebug,
&PixelFormatTest::compressedDebugImplementationSpecific});
}
void PixelFormatTest::size() {
CORRADE_COMPARE(pixelSize(PixelFormat::R8I), 1);
CORRADE_COMPARE(pixelSize(PixelFormat::R16UI), 2);
CORRADE_COMPARE(pixelSize(PixelFormat::RGB8Unorm), 3);
CORRADE_COMPARE(pixelSize(PixelFormat::RGBA8Snorm), 4);
CORRADE_COMPARE(pixelSize(PixelFormat::RGB16I), 6);
CORRADE_COMPARE(pixelSize(PixelFormat::RGBA16F), 8);
CORRADE_COMPARE(pixelSize(PixelFormat::RGB32UI), 12);
CORRADE_COMPARE(pixelSize(PixelFormat::RGBA32F), 16);
}
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
void PixelFormatTest::sizeDeprecated() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_IGNORE_DEPRECATED_PUSH
pixelSize(PixelFormat::RGBA);
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(out.str(), "pixelSize(): called with deprecated GL-specific format, use GL::pixelSize() instead\n");
}
#endif
void PixelFormatTest::sizeImplementationSpecific() {
std::ostringstream out;
Error redirectError{&out};
pixelSize(pixelFormatWrap(0xdead));
CORRADE_COMPARE(out.str(), "pixelSize(): can't determine pixel size of an implementation-specific format\n");
}
void PixelFormatTest::isImplementationSpecific() {
constexpr bool a = isPixelFormatImplementationSpecific(PixelFormat::RGBA8Unorm);
constexpr bool b = isPixelFormatImplementationSpecific(PixelFormat(0x8000dead));
CORRADE_VERIFY(!a);
CORRADE_VERIFY(b);
}
void PixelFormatTest::wrap() {
constexpr PixelFormat a = pixelFormatWrap(0xdead);
CORRADE_COMPARE(UnsignedInt(a), 0x8000dead);
}
void PixelFormatTest::wrapInvalid() {
std::ostringstream out;
Error redirectError{&out};
pixelFormatWrap(0xdeadbeef);
CORRADE_COMPARE(out.str(), "pixelFormatWrap(): implementation-specific value already wrapped or too large\n");
}
void PixelFormatTest::unwrap() {
constexpr UnsignedInt a = pixelFormatUnwrap(PixelFormat(0x8000dead));
CORRADE_COMPARE(a, 0xdead);
}
void PixelFormatTest::unwrapInvalid() {
std::ostringstream out;
Error redirectError{&out};
pixelFormatUnwrap(PixelFormat(0xdead));
CORRADE_COMPARE(out.str(), "pixelFormatUnwrap(): format doesn't contain a wrapped implementation-specific value\n");
}
void PixelFormatTest::compressedIsImplementationSpecific() {
CORRADE_VERIFY(!isPixelFormatImplementationSpecific(PixelFormat::RGBA8Unorm));
CORRADE_VERIFY(isPixelFormatImplementationSpecific(pixelFormatWrap(0xdead)));
}
void PixelFormatTest::compressedWrap() {
CORRADE_COMPARE(UnsignedInt(pixelFormatWrap(0xdead)), 0x8000dead);
}
void PixelFormatTest::compressedWrapInvalid() {
std::ostringstream out;
Error redirectError{&out};
compressedPixelFormatWrap(0xdeadbeef);
CORRADE_COMPARE(out.str(), "compressedPixelFormatWrap(): implementation-specific value already wrapped or too large\n");
}
void PixelFormatTest::compressedUnwrap() {
CORRADE_COMPARE(UnsignedInt(compressedPixelFormatUnwrap(CompressedPixelFormat(0x8000dead))), 0xdead);
}
void PixelFormatTest::compressedUnwrapInvalid() {
std::ostringstream out;
Error redirectError{&out};
compressedPixelFormatUnwrap(CompressedPixelFormat(0xdead));
CORRADE_COMPARE(out.str(), "compressedPixelFormatUnwrap(): format doesn't contain a wrapped implementation-specific value\n");
}
void PixelFormatTest::debug() {
std::ostringstream out;
Debug{&out} << PixelFormat::RG16Snorm << PixelFormat(0xdead);
CORRADE_COMPARE(out.str(), "PixelFormat::RG16Snorm PixelFormat(0xdead)\n");
}
void PixelFormatTest::debugImplementationSpecific() {
std::ostringstream out;
Debug{&out} << pixelFormatWrap(0xdead);
CORRADE_COMPARE(out.str(), "PixelFormat::ImplementationSpecific(0xdead)\n");
}
void PixelFormatTest::compressedDebug() {
std::ostringstream out;
Debug{&out} << CompressedPixelFormat::Bc3RGBAUnorm << CompressedPixelFormat(0xdead);
CORRADE_COMPARE(out.str(), "CompressedPixelFormat::Bc3RGBAUnorm CompressedPixelFormat(0xdead)\n");
}
void PixelFormatTest::compressedDebugImplementationSpecific() {
std::ostringstream out;
Debug{&out} << compressedPixelFormatWrap(0xdead);
CORRADE_COMPARE(out.str(), "CompressedPixelFormat::ImplementationSpecific(0xdead)\n");
}
}}
CORRADE_TEST_MAIN(Magnum::Test::PixelFormatTest)

34
src/Magnum/Trade/ImageData.cpp

@ -25,12 +25,22 @@
#include "ImageData.h" #include "ImageData.h"
#include "Magnum/PixelFormat.h"
namespace Magnum { namespace Trade { namespace Magnum { namespace Trade {
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: _compressed{false}, _storage{storage}, _format{format}, _type{type}, _size{size}, _data{std::move(data)}, _importerState{importerState} { template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, format, {}, Magnum::pixelSize(format), size, std::move(data), importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data), importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: _compressed{false}, _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _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), ); CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Trade::ImageData::ImageData(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), );
} }
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: _compressed{true}, _compressedStorage{storage}, _compressedFormat{format}, _size{size}, _data{std::move(data)}, _importerState{importerState} {}
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, compressedPixelFormatWrap(format), size, std::move(data), importerState} {}
template<UnsignedInt dimensions> PixelStorage ImageData<dimensions>::storage() const { template<UnsignedInt dimensions> PixelStorage ImageData<dimensions>::storage() const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData::storage(): the image is compressed", {}); CORRADE_ASSERT(!_compressed, "Trade::ImageData::storage(): the image is compressed", {});
return _storage; return _storage;
@ -41,26 +51,24 @@ template<UnsignedInt dimensions> PixelFormat ImageData<dimensions>::format() con
return _format; return _format;
} }
template<UnsignedInt dimensions> PixelType ImageData<dimensions>::type() const { template<UnsignedInt dimensions> UnsignedInt ImageData<dimensions>::formatExtra() const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData::type(): the image is compressed", {}); CORRADE_ASSERT(!_compressed, "Trade::ImageData::formatExtra(): the image is compressed", {});
return _type; return _formatExtra;
} }
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> CompressedPixelStorage ImageData<dimensions>::compressedStorage() const { template<UnsignedInt dimensions> CompressedPixelStorage ImageData<dimensions>::compressedStorage() const {
CORRADE_ASSERT(_compressed, "Trade::ImageData::compressedStorage(): the image is not compressed", {}); CORRADE_ASSERT(_compressed, "Trade::ImageData::compressedStorage(): the image is not compressed", {});
return _compressedStorage; return _compressedStorage;
} }
#endif
template<UnsignedInt dimensions> CompressedPixelFormat ImageData<dimensions>::compressedFormat() const { template<UnsignedInt dimensions> CompressedPixelFormat ImageData<dimensions>::compressedFormat() const {
CORRADE_ASSERT(_compressed, "Trade::ImageData::compressedFormat(): the image is not compressed", {}); CORRADE_ASSERT(_compressed, "Trade::ImageData::compressedFormat(): the image is not compressed", {});
return _compressedFormat; return _compressedFormat;
} }
template<UnsignedInt dimensions> std::size_t ImageData<dimensions>::pixelSize() const { template<UnsignedInt dimensions> UnsignedInt ImageData<dimensions>::pixelSize() const {
CORRADE_ASSERT(!_compressed, "Trade::ImageData::pixelSize(): the image is compressed", {}); CORRADE_ASSERT(!_compressed, "Trade::ImageData::pixelSize(): the image is compressed", {});
return PixelStorage::pixelSize(_format, _type); return _pixelSize;
} }
template<UnsignedInt dimensions> std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> ImageData<dimensions>::dataProperties() const { template<UnsignedInt dimensions> std::tuple<VectorTypeFor<dimensions, std::size_t>, VectorTypeFor<dimensions, std::size_t>, std::size_t> ImageData<dimensions>::dataProperties() const {
@ -70,21 +78,15 @@ template<UnsignedInt dimensions> std::tuple<VectorTypeFor<dimensions, std::size_
template<UnsignedInt dimensions> ImageData<dimensions>::operator ImageView<dimensions>() const template<UnsignedInt dimensions> ImageData<dimensions>::operator ImageView<dimensions>() const
{ {
CORRADE_ASSERT(!_compressed, "Trade::ImageData::type(): the image is compressed", (ImageView<dimensions>{_storage, _format, _type, _size})); CORRADE_ASSERT(!_compressed, "Trade::ImageData::type(): the image is compressed", (ImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size}));
return ImageView<dimensions>{_storage, _format, _type, _size, _data}; return ImageView<dimensions>{_storage, _format, _formatExtra, _pixelSize, _size, _data};
} }
template<UnsignedInt dimensions> ImageData<dimensions>::operator CompressedImageView<dimensions>() const template<UnsignedInt dimensions> ImageData<dimensions>::operator CompressedImageView<dimensions>() const
{ {
#ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(_compressed, "Trade::ImageData::type(): the image is not compressed", (CompressedImageView<dimensions>{_compressedStorage, _compressedFormat, _size})); CORRADE_ASSERT(_compressed, "Trade::ImageData::type(): the image is not compressed", (CompressedImageView<dimensions>{_compressedStorage, _compressedFormat, _size}));
#else
CORRADE_ASSERT(_compressed, "Trade::ImageData::type(): the image is not compressed", (CompressedImageView<dimensions>{_compressedFormat, _size}));
#endif
return CompressedImageView<dimensions>{ return CompressedImageView<dimensions>{
#ifndef MAGNUM_TARGET_GLES
_compressedStorage, _compressedStorage,
#endif
_compressedFormat, _size, _data}; _compressedFormat, _size, _data};
} }

251
src/Magnum/Trade/ImageData.h

@ -39,16 +39,41 @@ namespace Magnum { namespace Trade {
/** /**
@brief Image data @brief Image data
Access to either uncompressed or compressed image data provided by Used mainly by @ref AbstractImporter classes to store either compressed or
@ref AbstractImporter subclasses, the compression state is distinguished with non-compressed multi-dimensional image data together with layout and pixel
@ref isCompressed(). Uncompressed images have @ref format(), @ref type(), format description.
@ref pixelSize() and @ref dataProperties() properties and are convertible to
@ref ImageView. Compressed images have just the @ref compressedFormat() This class can act as a drop-in replacement for @ref Image or
property and are convertible to @ref CompressedImageView. @ref CompressedImage, @ref ImageView or @ref CompressedImageView and is
implicitly convertible to either @ref ImageView or @ref CompressedImageView.
Uncompressed image is interchangeable with @ref Image, @ref ImageView or Particular graphics API wrappers provide additional image classes, for example
@ref BufferImage, compressed with @ref CompressedImage, @ref CompressedImageView @ref GL::BufferImage or @ref GL::CompressedBufferImage.
or @ref CompressedBufferImage.
@section Trade-ImageData-usage Basic usage
The image usually comes out of @ref AbstractImporter::image1D(),
@ref AbstractImporter::image2D() "image2D()" or
@ref AbstractImporter::image3D() "image3D()" and, based on what format the
particular imported data is in, it stores either compressed or uncompressed
data.
@snippet MagnumTrade.cpp ImageData-construction
@snippet MagnumTrade.cpp ImageData-construction-compressed
As with @ref Image / @ref ImageView, this class supports extra storage
parameters and implementation-specific format specification, if the importer
has a need for that. See the @ref ImageView documentation for more information.
When using the image, its compression status can be distinguished using
@ref isCompressed(). Uncompressed image properties are available through
@ref storage(), @ref format(), @ref formatExtra() and @ref pixelSize();
compressed properties through @ref compressedStorage() and
@ref compressedFormat(). Example of uploading the image to
@link GL::Texture @endlink:
@snippet MagnumTrade.cpp ImageData-usage
@see @ref ImageData1D, @ref ImageData2D, @ref ImageData3D @see @ref ImageData1D, @ref ImageData2D, @ref ImageData3D
*/ */
template<UnsignedInt dimensions> class ImageData { template<UnsignedInt dimensions> class ImageData {
@ -61,22 +86,101 @@ template<UnsignedInt dimensions> class ImageData {
* @brief Construct uncompressed image data * @brief Construct uncompressed image data
* @param storage Storage of pixel data * @param storage Storage of pixel data
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
* @param importerState Importer-specific state * @param importerState Importer-specific state
* *
* The data are expected to be of proper size for given @p storage * The @p data array is expected to be of proper size for given
* parameters. * parameters.
*/ */
explicit ImageData(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept; explicit ImageData(PixelStorage storage, PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
/**
* @brief Construct uncompressed image data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param importerState Importer-specific state
*
* Equivalent to calling @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* with default-constructed @ref PixelStorage.
*/
explicit ImageData(PixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept: ImageData{{}, format, size, std::move(data), importerState} {}
/**
* @brief Construct uncompressed image data with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param pixelSize Size of a pixel in given format
* @param size Image size
* @param data Image data
* @param importerState Importer-specific state
*
* Unlike with @ref ImageData(PixelStorage, PixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*),
* where pixel size is calculated automatically using
* @ref pixelSize(PixelFormat), this allows you to specify an
* implementation-specific pixel format and pixel size directly. Uses
* @ref pixelFormatWrap() internally to wrap @p format in
* @ref Magnum::PixelFormat "PixelFormat".
*
* The @p data array is expected to be of proper size for given
* parameters.
*/
explicit ImageData(PixelStorage storage, UnsignedInt format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
/** @overload /** @overload
* Similar to the above, but uses default @ref PixelStorage parameters. *
* Equivalent to the above for @p format already wrapped with
* @ref pixelFormatWrap().
*/ */
explicit ImageData(PixelFormat format, PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept: ImageData{{}, format, type, size, std::move(data), importerState} {} explicit ImageData(PixelStorage storage, PixelFormat format, UnsignedInt formatExtra, UnsignedInt pixelSize, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
/**
* @brief Construct uncompressed image data with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param formatExtra Additional pixel format specifier
* @param size Image size
* @param data Image data
* @param importerState Importer-specific state
*
* Uses ADL to find a corresponding @cpp pixelSize(T, U) @ce overload,
* then calls @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* with calculated pixel size.
*/
template<class T, class U> explicit ImageData(PixelStorage storage, T format, U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
/**
* @brief Construct uncompressed image data with implementation-specific pixel format
* @param storage Storage of pixel data
* @param format Format of pixel data
* @param size Image size
* @param data Image data
* @param importerState Importer-specific state
*
* Uses ADL to find a corresponding @cpp pixelSize(T) @ce overload,
* then calls @ref ImageData(PixelStorage, UnsignedInt, UnsignedInt, UnsignedInt, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* with calculated pixel size and @p formatExtra set to @cpp 0 @ce.
*/
template<class T> explicit ImageData(PixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/**
* @brief Construct uncompressed image data
* @param format Format of pixel data
* @param type Data type of pixel data
* @param size Image size
* @param data Image data
* @param importerState Importer-specific state
*
* @deprecated Use the generic @ref ImageData(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* instead --- the pixel storage parameter is used to distinguish
* between compressed and uncompressed data.
*/
template<class = void> explicit CORRADE_DEPRECATED("use Image(PixelStorage, T, U, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*) instead") ImageData(PixelFormat format, GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
#endif
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Construct compressed image data * @brief Construct compressed image data
* @param storage Storage of compressed pixel data * @param storage Storage of compressed pixel data
@ -84,15 +188,8 @@ template<UnsignedInt dimensions> class ImageData {
* @param size Image size * @param size Image size
* @param data Image data * @param data Image data
* @param importerState Importer-specific state * @param importerState Importer-specific state
*
* Note that the image data are not copied on construction, but they
* are deleted on class destruction.
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept; explicit ImageData(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
#endif
/** /**
* @brief Construct compressed image data * @brief Construct compressed image data
@ -101,10 +198,23 @@ template<UnsignedInt dimensions> class ImageData {
* @param data Image data * @param data Image data
* @param importerState Importer-specific state * @param importerState Importer-specific state
* *
* Similar the above, but uses default @ref CompressedPixelStorage * Equivalent to calling @ref ImageData(CompressedPixelStorage, CompressedPixelFormat, const VectorTypeFor<dimensions, Int>&, Containers::Array<char>&&, const void*)
* parameters (or the hardcoded ones in OpenGL ES and WebGL). * with default-constructed @ref CompressedPixelStorage.
*/
explicit ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept: ImageData{{}, format, size, std::move(data), importerState} {}
/**
* @brief Construct compressed image data
* @param storage Storage of compressed pixel data
* @param format Format of compressed pixel data
* @param size Image size
* @param data Image data
* @param importerState Importer-specific state
*
* Uses @ref compressedPixelFormatWrap() internally to convert
* @p format to @ref CompressedPixelFormat.
*/ */
explicit ImageData(CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept; template<class T> explicit ImageData(CompressedPixelStorage storage, T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
ImageData(const ImageData<dimensions>&) = delete; ImageData(const ImageData<dimensions>&) = delete;
@ -152,35 +262,56 @@ template<UnsignedInt dimensions> class ImageData {
/** /**
* @brief Format of pixel data * @brief Format of pixel data
* *
* Returns either a defined value from the
* @ref Magnum::PixelFormat "PixelFormat" enum or a wrapped
* implementation-specific value. Use
* @ref isPixelFormatImplementationSpecific() to distinguish the case
* and @ref pixelFormatUnwrap() to extract an implementation-specific
* value, if needed.
*
* The image is expected to be uncompressed. * The image is expected to be uncompressed.
* @see @ref isCompressed(), @ref compressedFormat() * @see @ref isCompressed(), @ref compressedFormat()
*/ */
PixelFormat format() const; PixelFormat format() const;
/** /**
* @brief Data type of pixel data * @brief Additional pixel format specifier
*
* Some implementations (such as OpenGL) define a pixel format using
* two values. This field contains the second implementation-specific
* value verbatim, if any. See @ref format() for more information.
* *
* The image is expected to be uncompressed. * The image is expected to be uncompressed.
* @see @ref isCompressed() * @see @ref isCompressed()
*/ */
PixelType type() const; UnsignedInt formatExtra() const;
#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
/**
* @brief Data type of pixel data
*
* @deprecated Cast @ref formatExtra() to @ref GL::PixelType instead.
*/
CORRADE_DEPRECATED("cast formatExtra() to GL::PixelType instead") GL::PixelType type() const { return GL::PixelType(formatExtra()); }
#endif
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Storage of compressed pixel data * @brief Storage of compressed pixel data
* *
* The image is expected to be compressed. * The image is expected to be compressed.
* @see @ref isCompressed(), @ref storage()) * @see @ref isCompressed(), @ref storage()
* @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage}
* @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and
* WebGL.
*/ */
CompressedPixelStorage compressedStorage() const; CompressedPixelStorage compressedStorage() const;
#endif
/** /**
* @brief Format of compressed pixel data * @brief Format of compressed pixel data
* *
* Returns either a defined value from the @ref CompressedPixelFormat
* enum or a wrapped implementation-specific value. Use
* @ref isCompressedPixelFormatImplementationSpecific() to distinguish
* the case and @ref compressedPixelFormatUnwrap() to extract an
* implementation-specific value, if needed.
*
* The image is expected to be compressed. * The image is expected to be compressed.
* @see @ref isCompressed(), @ref format() * @see @ref isCompressed(), @ref format()
*/ */
@ -192,7 +323,7 @@ template<UnsignedInt dimensions> class ImageData {
* The image is expected to be uncompressed. * The image is expected to be uncompressed.
* @see @ref isCompressed(), @ref Magnum::pixelSize() * @see @ref isCompressed(), @ref Magnum::pixelSize()
*/ */
std::size_t pixelSize() const; UnsignedInt pixelSize() const;
/** @brief Image size */ /** @brief Image size */
VectorTypeFor<dimensions, Int> size() const { return _size; } VectorTypeFor<dimensions, Int> size() const { return _size; }
@ -261,18 +392,19 @@ template<UnsignedInt dimensions> class ImageData {
const void* importerState() const { return _importerState; } const void* importerState() const { return _importerState; }
private: private:
explicit ImageData(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState = nullptr) noexcept;
bool _compressed; bool _compressed;
union { union {
PixelStorage _storage; PixelStorage _storage;
#ifndef MAGNUM_TARGET_GLES
CompressedPixelStorage _compressedStorage; CompressedPixelStorage _compressedStorage;
#endif
}; };
union { union {
PixelFormat _format; PixelFormat _format;
CompressedPixelFormat _compressedFormat; CompressedPixelFormat _compressedFormat;
}; };
PixelType _type; UnsignedInt _formatExtra;
UnsignedInt _pixelSize;
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;
Containers::Array<char> _data; Containers::Array<char> _data;
const void* _importerState; const void* _importerState;
@ -287,31 +419,43 @@ typedef ImageData<2> ImageData2D;
/** @brief Three-dimensional image */ /** @brief Three-dimensional image */
typedef ImageData<3> ImageData3D; typedef ImageData<3> ImageData3D;
template<UnsignedInt dimensions> ImageData<dimensions>::ImageData( template<UnsignedInt dimensions> template<class T, class U> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const U formatExtra, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage,
#ifndef MAGNUM_TARGET_GLES #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
const CompressedPixelStorage storage, Implementation::wrapPixelFormatIfNotGLSpecific(format),
#else
UnsignedInt(format),
#endif #endif
const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* importerState) noexcept: _compressed{true}, UnsignedInt(formatExtra), Implementation::pixelSizeAdl(format, formatExtra), size, std::move(data), importerState} {
#ifndef MAGNUM_TARGET_GLES static_assert(sizeof(T) <= 4 && sizeof(U) <= 4,
_compressedStorage{storage}, "format types larger than 32bits are not supported");
#endif }
_compressedFormat{format}, _size{size}, _data{std::move(data)}, _importerState{importerState} {}
#ifndef MAGNUM_TARGET_GLES #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL)
template<UnsignedInt dimensions> inline ImageData<dimensions>::ImageData(const CompressedPixelFormat format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{{}, format, size, std::move(data), importerState} {} CORRADE_IGNORE_DEPRECATED_PUSH
template<UnsignedInt dimensions> template<class> inline ImageData<dimensions>::ImageData(const PixelFormat format, const GL::PixelType type, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{PixelStorage{}, format, type, size, std::move(data), importerState} {}
CORRADE_IGNORE_DEPRECATED_POP
#endif #endif
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const PixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), {}, Implementation::pixelSizeAdl(format), size, std::move(data), importerState} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> template<class T> ImageData<dimensions>::ImageData(const CompressedPixelStorage storage, const T format, const VectorTypeFor<dimensions, Int>& size, Containers::Array<char>&& data, const void* const importerState) noexcept: ImageData{storage, UnsignedInt(format), size, std::move(data), importerState} {
static_assert(sizeof(T) <= 4,
"format types larger than 32bits are not supported");
}
template<UnsignedInt dimensions> inline ImageData<dimensions>::ImageData(ImageData<dimensions>&& other) noexcept: _compressed{std::move(other._compressed)}, _size{std::move(other._size)}, _data{std::move(other._data)}, _importerState{std::move(other._importerState)} { template<UnsignedInt dimensions> inline ImageData<dimensions>::ImageData(ImageData<dimensions>&& other) noexcept: _compressed{std::move(other._compressed)}, _size{std::move(other._size)}, _data{std::move(other._data)}, _importerState{std::move(other._importerState)} {
if(_compressed) { if(_compressed) {
#ifndef MAGNUM_TARGET_GLES
new(&_compressedStorage) CompressedPixelStorage{std::move(other._compressedStorage)}; new(&_compressedStorage) CompressedPixelStorage{std::move(other._compressedStorage)};
#endif
_compressedFormat = std::move(other._compressedFormat); _compressedFormat = std::move(other._compressedFormat);
} }
else { else {
new(&_storage) PixelStorage{std::move(other._storage)}; new(&_storage) PixelStorage{std::move(other._storage)};
_format = std::move(other._format); _format = std::move(other._format);
_type = std::move(other._type); _formatExtra = std::move(other._formatExtra);
_pixelSize = std::move(other._pixelSize);
} }
other._size = {}; other._size = {};
@ -321,16 +465,15 @@ template<UnsignedInt dimensions> inline ImageData<dimensions>& ImageData<dimensi
using std::swap; using std::swap;
swap(_compressed, other._compressed); swap(_compressed, other._compressed);
if(_compressed) { if(_compressed) {
#ifndef MAGNUM_TARGET_GLES
swap(_compressedStorage, other._compressedStorage); swap(_compressedStorage, other._compressedStorage);
#endif
swap(_compressedFormat, other._compressedFormat); swap(_compressedFormat, other._compressedFormat);
} }
else { else {
swap(_storage, other._storage); swap(_storage, other._storage);
swap(_format, other._format); swap(_format, other._format);
} }
swap(_type, other._type); swap(_formatExtra, other._formatExtra);
swap(_pixelSize, other._pixelSize);
swap(_size, other._size); swap(_size, other._size);
swap(_data, other._data); swap(_data, other._data);
swap(_importerState, other._importerState); swap(_importerState, other._importerState);

Loading…
Cancel
Save