Browse Source

GL: make it possible to read pixel data into mutable image views.

UGH I hate cube maps and all the driver bugs that make them so freaking
annoying to implement.
pull/362/head
Vladimír Vondruš 7 years ago
parent
commit
07b3253714
  1. 6
      doc/changelog.dox
  2. 29
      src/Magnum/GL/AbstractFramebuffer.cpp
  3. 20
      src/Magnum/GL/AbstractFramebuffer.h
  4. 132
      src/Magnum/GL/AbstractTexture.cpp
  5. 4
      src/Magnum/GL/AbstractTexture.h
  6. 6
      src/Magnum/GL/CMakeLists.txt
  7. 133
      src/Magnum/GL/CubeMapTexture.cpp
  8. 61
      src/Magnum/GL/CubeMapTexture.h
  9. 47
      src/Magnum/GL/CubeMapTextureArray.h
  10. 46
      src/Magnum/GL/RectangleTexture.h
  11. 258
      src/Magnum/GL/Test/AbstractTextureGLTest.cpp
  12. 8
      src/Magnum/GL/Test/CMakeLists.txt
  13. 147
      src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp
  14. 542
      src/Magnum/GL/Test/CubeMapTextureGLTest.cpp
  15. 104
      src/Magnum/GL/Test/FramebufferGLTest.cpp
  16. 70
      src/Magnum/GL/Test/RectangleTextureGLTest.cpp
  17. 211
      src/Magnum/GL/Test/TextureArrayGLTest.cpp
  18. 338
      src/Magnum/GL/Test/TextureGLTest.cpp
  19. 70
      src/Magnum/GL/Texture.h
  20. 47
      src/Magnum/GL/TextureArray.h

6
doc/changelog.dox

@ -131,6 +131,12 @@ See also:
- Added an ability to use Magnum with multiple OpenGL contexts using - Added an ability to use Magnum with multiple OpenGL contexts using
@ref GL::Context::makeCurrent(), see @ref GL-Context-multiple for more @ref GL::Context::makeCurrent(), see @ref GL-Context-multiple for more
information information
- @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(),
@ref GL::Texture::subImage(), @ref GL::Texture::compressedImage(),
@ref GL::Texture::setCompressedSubImage() and equivalent APIs in other
texture classes now can read the pixels into
@ref BasicMutableImageView "MutableImageView*D" and
@ref BasicMutableCompressedImageView "MutableCompressedImageView*D" as well
@subsubsection changelog-latest-new-math Math library @subsubsection changelog-latest-new-math Math library

29
src/Magnum/GL/AbstractFramebuffer.cpp

@ -26,6 +26,7 @@
#include "AbstractFramebuffer.h" #include "AbstractFramebuffer.h"
#include "Magnum/Image.h" #include "Magnum/Image.h"
#include "Magnum/ImageView.h"
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#include "Magnum/GL/BufferImage.h" #include "Magnum/GL/BufferImage.h"
#endif #endif
@ -334,25 +335,35 @@ AbstractFramebuffer& AbstractFramebuffer::clearDepthStencil(const Float depth, c
} }
#endif #endif
void AbstractFramebuffer::read(const Range2Di& rectangle, Image2D& image) { void AbstractFramebuffer::read(const Range2Di& rectangle, MutableImageView2D& image) {
bindInternal(FramebufferTarget::Read); CORRADE_ASSERT(image.data().data() != nullptr,
"GL::AbstractFramebuffer::read(): image view is nullptr", );
/* Reallocate only if needed */ CORRADE_ASSERT(image.size() == rectangle.size(),
const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, rectangle.size()); "GL::AbstractFramebuffer::read(): expected image view size" << rectangle.size() << "but got" << image.size(), );
Containers::Array<char> data{image.release()};
if(data.size() < dataSize)
data = Containers::Array<char>{dataSize};
bindInternal(FramebufferTarget::Read);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
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, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data (Context::current().state().framebuffer->readImplementation)(rectangle, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size()) + Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size())
#endif #endif
); );
}
void AbstractFramebuffer::read(const Range2Di& rectangle, Image2D& image) {
/* Reallocate only if needed */
const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, rectangle.size());
Containers::Array<char> data{image.release()};
if(data.size() < dataSize)
data = Containers::Array<char>{dataSize};
/* Replace the storage, proxy to the function taking a view */
image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), rectangle.size(), std::move(data)}; image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), rectangle.size(), std::move(data)};
MutableImageView2D view(image);
read(rectangle, view);
} }
Image2D AbstractFramebuffer::read(const Range2Di& rectangle, Image2D&& image) { Image2D AbstractFramebuffer::read(const Range2Di& rectangle, Image2D&& image) {

20
src/Magnum/GL/AbstractFramebuffer.h

@ -380,11 +380,13 @@ class MAGNUM_GL_EXPORT AbstractFramebuffer {
* *
* Image parameters like format and type of pixel data are taken from * Image parameters like format and type of pixel data are taken from
* given image. The storage is not reallocated if it is large enough to * given image. The storage is not reallocated if it is large enough to
* contain the new data. On OpenGL ES 2.0 and WebGL 1.0, if * contain the new data --- however if you want to read into existing
* @ref PixelStorage::skip() is set, the functionality is emulated by * memory or *ensure* a reallocation does not happen, use
* adjusting the data pointer. * @ref read(const Range2Di&, MutableImageView2D&) instead.
* *
* If @gl_extension{ARB,robustness} is available, the operation is * On OpenGL ES 2.0 and WebGL 1.0, if @ref PixelStorage::skip() is set,
* the functionality is emulated by adjusting the data pointer. If
* @gl_extension{ARB,robustness} is available, the operation is
* protected from buffer overflow. * protected from buffer overflow.
* @see @fn_gl{BindFramebuffer}, then @fn_gl{PixelStore} and * @see @fn_gl{BindFramebuffer}, then @fn_gl{PixelStore} and
* @fn_gl_keyword{ReadPixels} or * @fn_gl_keyword{ReadPixels} or
@ -405,6 +407,16 @@ class MAGNUM_GL_EXPORT AbstractFramebuffer {
*/ */
Image2D read(const Range2Di& rectangle, Image2D&& image); Image2D read(const Range2Di& rectangle, Image2D&& image);
/**
* @brief Read block of pixels from framebuffer to image
*
* Compared to @ref read(const Range2Di&, Image2D&) the function
* reads the pixels into the memory provided by @p image, expecting
* it's not @cpp nullptr @ce and its size is the same as @p rectangle
* size.
*/
void read(const Range2Di& rectangle, MutableImageView2D& image);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Read block of pixels from framebuffer to buffer image * @brief Read block of pixels from framebuffer to buffer image

132
src/Magnum/GL/AbstractTexture.cpp

@ -1602,6 +1602,24 @@ template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, Image<1>&);
template void MAGNUM_GL_EXPORT AbstractTexture::image<2>(GLint, Image<2>&); template void MAGNUM_GL_EXPORT AbstractTexture::image<2>(GLint, Image<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::image<3>(GLint, Image<3>&); template void MAGNUM_GL_EXPORT AbstractTexture::image<3>(GLint, Image<3>&);
template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, BasicMutableImageView<dimensions>& image) {
#ifndef CORRADE_NO_ASSERT
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::AbstractTexture::image(): image view is nullptr", );
CORRADE_ASSERT(image.size() == size,
"GL::AbstractTexture::image(): expected image view size" << size << "but got" << image.size(), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data());
}
template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, BasicMutableImageView<1>&);
template void MAGNUM_GL_EXPORT AbstractTexture::image<2>(GLint, BasicMutableImageView<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::image<3>(GLint, BasicMutableImageView<3>&);
template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, BufferImage<dimensions>& image, BufferUsage usage) { template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, BufferImage<dimensions>& image, BufferUsage usage) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level); const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, size); const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, size);
@ -1652,6 +1670,45 @@ template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, Compre
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<2>(GLint, CompressedImage<2>&); template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<2>(GLint, CompressedImage<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<3>(GLint, CompressedImage<3>&); template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<3>(GLint, CompressedImage<3>&);
template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLint level, BasicMutableCompressedImageView<dimensions>& image) {
#ifndef CORRADE_NO_ASSERT
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::AbstractTexture::compressedImage(): image view is nullptr", );
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
CORRADE_ASSERT(image.size() == size,
"GL::AbstractTexture::compressedImage(): expected image view size" << size << "but got" << image.size(), );
/* If the user-provided pixel storage doesn't tell us all properties about
the compression, we need to ask GL for it */
std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
GLint textureDataSize;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
dataSize = textureDataSize;
} else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
CORRADE_ASSERT(image.data().size() == dataSize,
"GL::AbstractTexture::compressedImage(): expected image view data size" << dataSize << "bytes but got" << image.data().size(), );
/* Internal texture format */
GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::AbstractTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedImageImplementation)(level, image.data().size(), image.data());
}
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, BasicMutableCompressedImageView<1>&);
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<2>(GLint, BasicMutableCompressedImageView<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<3>(GLint, BasicMutableCompressedImageView<3>&);
template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLint level, CompressedBufferImage<dimensions>& image, BufferUsage usage) { template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLint level, CompressedBufferImage<dimensions>& image, BufferUsage usage) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level); const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, level);
@ -1684,28 +1741,43 @@ template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<2>(GLint, Compre
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<3>(GLint, CompressedBufferImage<3>&, BufferUsage); template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<3>(GLint, CompressedBufferImage<3>&, BufferUsage);
template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, Image<dimensions>& image) { template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, Image<dimensions>& image) {
createIfNotAlready(); /* Reallocate only if needed */
const Math::Vector<dimensions, Int> size = range.size(); const Math::Vector<dimensions, Int> size = range.size();
const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, size); const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, size);
const Vector3i paddedOffset = Vector3i::pad<dimensions>(range.min());
const Vector3i paddedSize = Vector3i::pad(size, 1);
/* Reallocate only if needed */
Containers::Array<char> data{image.release()}; Containers::Array<char> data{image.release()};
if(data.size() < dataSize) if(data.size() < dataSize)
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
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.formatExtra(), image.pixelSize(), size, std::move(data)}; image = Image<dimensions>{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
BasicMutableImageView<dimensions> view(image);
subImage(level, range, view);
} }
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>&);
template void MAGNUM_GL_EXPORT AbstractTexture::subImage<2>(GLint, const Range2Di&, Image<2>&); template void MAGNUM_GL_EXPORT AbstractTexture::subImage<2>(GLint, const Range2Di&, Image<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::subImage<3>(GLint, const Range3Di&, Image<3>&); template void MAGNUM_GL_EXPORT AbstractTexture::subImage<3>(GLint, const Range3Di&, Image<3>&);
template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, BasicMutableImageView<dimensions>& image) {
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::AbstractTexture::subImage(): image view is nullptr", );
CORRADE_ASSERT(image.size() == range.size(),
"GL::AbstractTexture::subImage(): expected image view size" << range.size() << "but got" << image.size(), );
createIfNotAlready();
const Math::Vector<dimensions, Int> size = range.size();
const Vector3i paddedOffset = Vector3i::pad<dimensions>(range.min());
const Vector3i paddedSize = Vector3i::pad(size, 1);
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
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())), image.data().size(), image.data());
}
template void MAGNUM_GL_EXPORT AbstractTexture::subImage<1>(GLint, const Range1Di&, BasicMutableImageView<1>&);
template void MAGNUM_GL_EXPORT AbstractTexture::subImage<2>(GLint, const Range2Di&, BasicMutableImageView<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::subImage<3>(GLint, const Range3Di&, BasicMutableImageView<3>&);
template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, BufferImage<dimensions>& image, const BufferUsage usage) { template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, BufferImage<dimensions>& image, const BufferUsage usage) {
createIfNotAlready(); createIfNotAlready();
@ -1775,6 +1847,48 @@ template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<1>(GLint, con
template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<2>(GLint, const Range2Di&, CompressedImage<2>&); template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<2>(GLint, const Range2Di&, CompressedImage<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<3>(GLint, const Range3Di&, CompressedImage<3>&); template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<3>(GLint, const Range3Di&, CompressedImage<3>&);
template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, BasicMutableCompressedImageView<dimensions>& image) {
#ifndef CORRADE_NO_ASSERT
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::AbstractTexture::compressedSubImage(): image view is nullptr", );
CORRADE_ASSERT(image.size() == range.size(),
"GL::AbstractTexture::compressedSubImage(): expected image view size" << range.size() << "but got" << image.size(), );
createIfNotAlready();
const Math::Vector<dimensions, Int> size = range.size();
/* Internal texture format */
GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::AbstractTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
/* Calculate compressed subimage size. If the user-provided pixel storage
doesn't tell us all properties about the compression, we need to ask GL
for it. That requires GL_ARB_internalformat_query2. */
std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
dataSize = compressedSubImageSize<dimensions>(TextureFormat(format), size);
else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
CORRADE_ASSERT(image.data().size() == dataSize,
"GL::AbstractTexture::compressedSubImage(): expected image view data size" << dataSize << "bytes but got" << image.data().size(), );
#endif
const Vector3i paddedOffset = Vector3i::pad<dimensions>(range.min());
const Vector3i paddedSize = Vector3i::pad(size, 1);
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), image.data().size(), image.data());
}
template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<1>(GLint, const Range1Di&, BasicMutableCompressedImageView<1>&);
template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<2>(GLint, const Range2Di&, BasicMutableCompressedImageView<2>&);
template void MAGNUM_GL_EXPORT AbstractTexture::compressedSubImage<3>(GLint, const Range3Di&, BasicMutableCompressedImageView<3>&);
template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, CompressedBufferImage<dimensions>& image, const BufferUsage usage) { template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const GLint level, const RangeTypeFor<dimensions, Int>& range, CompressedBufferImage<dimensions>& image, const BufferUsage usage) {
createIfNotAlready(); createIfNotAlready();

4
src/Magnum/GL/AbstractTexture.h

@ -489,12 +489,16 @@ class MAGNUM_GL_EXPORT AbstractTexture: public AbstractObject {
void generateMipmap(); void generateMipmap();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> void image(GLint level, BasicMutableImageView<dimensions>& image);
template<UnsignedInt dimensions> void image(GLint level, Image<dimensions>& image); template<UnsignedInt dimensions> void image(GLint level, Image<dimensions>& image);
template<UnsignedInt dimensions> void image(GLint level, BufferImage<dimensions>& image, BufferUsage usage); template<UnsignedInt dimensions> void image(GLint level, BufferImage<dimensions>& image, BufferUsage usage);
template<UnsignedInt dimensions> void compressedImage(GLint level, BasicMutableCompressedImageView<dimensions>& image);
template<UnsignedInt dimensions> void compressedImage(GLint level, CompressedImage<dimensions>& image); template<UnsignedInt dimensions> void compressedImage(GLint level, CompressedImage<dimensions>& image);
template<UnsignedInt dimensions> void compressedImage(GLint level, CompressedBufferImage<dimensions>& image, BufferUsage usage); template<UnsignedInt dimensions> void compressedImage(GLint level, CompressedBufferImage<dimensions>& image, BufferUsage usage);
template<UnsignedInt dimensions> void subImage(GLint level, const RangeTypeFor<dimensions, Int>& range, BasicMutableImageView<dimensions>& image);
template<UnsignedInt dimensions> void subImage(GLint level, const RangeTypeFor<dimensions, Int>& range, Image<dimensions>& image); template<UnsignedInt dimensions> void subImage(GLint level, const RangeTypeFor<dimensions, Int>& range, Image<dimensions>& image);
template<UnsignedInt dimensions> void subImage(GLint level, const RangeTypeFor<dimensions, Int>& range, BufferImage<dimensions>& image, BufferUsage usage); template<UnsignedInt dimensions> void subImage(GLint level, const RangeTypeFor<dimensions, Int>& range, BufferImage<dimensions>& image, BufferUsage usage);
template<UnsignedInt dimensions> void compressedSubImage(GLint level, const RangeTypeFor<dimensions, Int>& range, BasicMutableCompressedImageView<dimensions>& image);
template<UnsignedInt dimensions> void compressedSubImage(GLint level, const RangeTypeFor<dimensions, Int>& range, CompressedImage<dimensions>& image); template<UnsignedInt dimensions> void compressedSubImage(GLint level, const RangeTypeFor<dimensions, Int>& range, CompressedImage<dimensions>& image);
template<UnsignedInt dimensions> void compressedSubImage(GLint level, const RangeTypeFor<dimensions, Int>& range, CompressedBufferImage<dimensions>& image, BufferUsage usage); template<UnsignedInt dimensions> void compressedSubImage(GLint level, const RangeTypeFor<dimensions, Int>& range, CompressedBufferImage<dimensions>& image, BufferUsage usage);
#endif #endif

6
src/Magnum/GL/CMakeLists.txt

@ -24,13 +24,10 @@
# #
set(MagnumGL_SRCS set(MagnumGL_SRCS
AbstractFramebuffer.cpp
AbstractObject.cpp AbstractObject.cpp
AbstractTexture.cpp
AbstractShaderProgram.cpp AbstractShaderProgram.cpp
Attribute.cpp Attribute.cpp
Buffer.cpp Buffer.cpp
CubeMapTexture.cpp
Context.cpp Context.cpp
DefaultFramebuffer.cpp DefaultFramebuffer.cpp
Framebuffer.cpp Framebuffer.cpp
@ -54,6 +51,9 @@ set(MagnumGL_SRCS
Implementation/maxTextureSize.cpp) Implementation/maxTextureSize.cpp)
set(MagnumGL_GracefulAssert_SRCS set(MagnumGL_GracefulAssert_SRCS
AbstractFramebuffer.cpp
AbstractTexture.cpp
CubeMapTexture.cpp
Mesh.cpp Mesh.cpp
MeshView.cpp MeshView.cpp
PixelFormat.cpp PixelFormat.cpp

133
src/Magnum/GL/CubeMapTexture.cpp

@ -85,6 +85,20 @@ Image3D CubeMapTexture::image(const Int level, Image3D&& image) {
return std::move(image); return std::move(image);
} }
void CubeMapTexture::image(const Int level, MutableImageView3D& image) {
#ifndef CORRADE_NO_ASSERT
const Vector3i size{imageSize(level), 6};
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::CubeMapTexture::image(): image view is nullptr", );
CORRADE_ASSERT(image.size() == size,
"GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
glGetTextureImage(_id, level, GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data().size(), image.data());
}
void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUsage usage) { void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUsage usage) {
createIfNotAlready(); createIfNotAlready();
@ -140,6 +154,40 @@ CompressedImage3D CubeMapTexture::compressedImage(const Int level, CompressedIma
return std::move(image); return std::move(image);
} }
void CubeMapTexture::compressedImage(const Int level, MutableCompressedImageView3D& image) {
#ifndef CORRADE_NO_ASSERT
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::CubeMapTexture::compressedImage(): image view is nullptr", );
const Vector3i size{imageSize(level), 6};
CORRADE_ASSERT(image.size() == size,
"GL::CubeMapTexture::compressedImage(): expected image view size" << size << "but got" << image.size(), );
/* If the user-provided pixel storage doesn't tell us all properties about
the compression, we need to ask GL for it */
std::pair<std::size_t, std::size_t> dataOffsetSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
dataOffsetSize.first = 0;
dataOffsetSize.second = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level)*6;
} else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size);
CORRADE_ASSERT(image.data().size() == dataOffsetSize.first + dataOffsetSize.second,
"GL::CubeMapTexture::compressedImage(): expected image view data size" << dataOffsetSize.first + dataOffsetSize.second << "bytes but got" << image.data().size(), );
/* Internal texture format */
GLint format;
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data());
}
void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& image, const BufferUsage usage) { void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& image, const BufferUsage usage) {
createIfNotAlready(); createIfNotAlready();
@ -193,6 +241,20 @@ Image2D CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int leve
return std::move(image); return std::move(image);
} }
void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, MutableImageView2D& image) {
#ifndef CORRADE_NO_ASSERT
const Vector2i size = imageSize(level);
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::CubeMapTexture::image(): image view is nullptr", );
CORRADE_ASSERT(image.size() == size,
"GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data());
}
void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D& image, const BufferUsage usage) { void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D& image, const BufferUsage usage) {
const Vector2i size = imageSize(level); const Vector2i size = imageSize(level);
const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, size); const std::size_t dataSize = Magnum::Implementation::imageDataSizeFor(image, size);
@ -246,6 +308,42 @@ CompressedImage2D CubeMapTexture::compressedImage(const CubeMapCoordinate coordi
return std::move(image); return std::move(image);
} }
void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, MutableCompressedImageView2D& image) {
#ifndef CORRADE_NO_ASSERT
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::CubeMapTexture::compressedImage(): image view is nullptr", );
const Vector2i size = imageSize(level);
CORRADE_ASSERT(image.size() == size,
"GL::CubeMapTexture::compressedImage(): expected image view size" << size << "but got" << image.size(), );
/* If the user-provided pixel storage doesn't tell us all properties about
the compression, we need to ask GL for it */
std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
dataSize = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level);
else
dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
CORRADE_ASSERT(image.data().size() == dataSize,
"GL::CubeMapTexture::compressedImage(): expected image view data size" << dataSize << "bytes but got" << image.data().size(), );
/* Internal texture format. Zero-init to avoid an assert about value
already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, image.data().size(), image.data());
}
void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) { void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) {
const Vector2i size = imageSize(level); const Vector2i size = imageSize(level);
@ -322,6 +420,41 @@ CompressedImage3D CubeMapTexture::compressedSubImage(const Int level, const Rang
return std::move(image); return std::move(image);
} }
void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, MutableCompressedImageView3D& image) {
#ifndef CORRADE_NO_ASSERT
CORRADE_ASSERT(image.data().data() != nullptr,
"GL::CubeMapTexture::compressedSubImage(): image view is nullptr", );
CORRADE_ASSERT(image.size() == range.size(),
"GL::CubeMapTexture::compressedSubImage(): expected image view size" << range.size() << "but got" << image.size(), );
createIfNotAlready();
/* Internal texture format. Zero-init to avoid an assert about value
already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::CubeMapTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
/* Calculate compressed subimage size. If the user-provided pixel storage
doesn't tell us all properties about the compression, we need to ask GL
for it. That requires GL_ARB_internalformat_query2. */
std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
dataSize = compressedSubImageSize<3>(TextureFormat(format), range.size());
else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, range.size());
CORRADE_ASSERT(image.data().size() == dataSize,
"GL::CubeMapTexture::compressedSubImage(): expected image view data size" << dataSize << "bytes but got" << image.data().size(), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), image.data().size(), image.data());
}
void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, CompressedBufferImage3D& image, const BufferUsage usage) { void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, CompressedBufferImage3D& image, const BufferUsage usage) {
createIfNotAlready(); createIfNotAlready();

61
src/Magnum/GL/CubeMapTexture.h

@ -565,6 +565,15 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
*/ */
Image3D image(Int level, Image3D&& image); Image3D image(Int level, Image3D&& image);
/**
* @brief Read given texture mip level to an image view
*
* Compared to @ref image(Int, Image3D&) the function reads the pixels
* into the memory provided by @p image, expecting it's not
* @cpp nullptr @ce and its size is the same as size of given @p level.
*/
void image(Int level, MutableImageView3D& image);
/** /**
* @brief Read given texture mip level to a buffer image * @brief Read given texture mip level to a buffer image
* *
@ -614,6 +623,16 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
*/ */
CompressedImage3D compressedImage(Int level, CompressedImage3D&& image); CompressedImage3D compressedImage(Int level, CompressedImage3D&& image);
/**
* @brief Read given compressed texture mip level to an image view
*
* Compared to @ref compressedImage(Int, CompressedImage3D&) the
* function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as size of given @p level.
*/
void compressedImage(Int level, MutableCompressedImageView3D& image);
/** /**
* @brief Read given compressed texture mip level to a buffer image * @brief Read given compressed texture mip level to a buffer image
* *
@ -671,6 +690,16 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
*/ */
Image2D image(CubeMapCoordinate coordinate, Int level, Image2D&& image); Image2D image(CubeMapCoordinate coordinate, Int level, Image2D&& image);
/**
* @brief Read given texture mip level and coordinate to an image view
*
* Compared to @ref image(CubeMapCoordinate, Int, Image2D&) the
* function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce and its size is the same as size
* of given @p level.
*/
void image(CubeMapCoordinate coordinate, Int level, MutableImageView2D& image);
/** /**
* @brief Read given texture mip level and coordinate to a buffer image * @brief Read given texture mip level and coordinate to a buffer image
* *
@ -727,6 +756,16 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
*/ */
CompressedImage2D compressedImage(CubeMapCoordinate coordinate, Int level, CompressedImage2D&& image); CompressedImage2D compressedImage(CubeMapCoordinate coordinate, Int level, CompressedImage2D&& image);
/**
* @brief Read given compressed texture mip level to an image view
*
* Compared to @ref compressedImage(CubeMapCoordinate, Int, CompressedImage2D&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as size of given @p level.
*/
void compressedImage(CubeMapCoordinate coordinate, Int level, MutableCompressedImageView2D& image);
/** /**
* @brief Read given compressed texture mip level and coordinate to a buffer image * @brief Read given compressed texture mip level and coordinate to a buffer image
* *
@ -772,6 +811,18 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
*/ */
Image3D subImage(Int level, const Range3Di& range, Image3D&& image); Image3D subImage(Int level, const Range3Di& range, Image3D&& image);
/**
* @brief Read a range of given texture mip level to an image view
*
* Compared to @ref subImage(Int, const Range3Di&, Image3D&) the
* function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce and its size is the same as
* @p range size.
*/
void subImage(Int level, const Range3Di& range, MutableImageView3D& image) {
AbstractTexture::subImage<3>(level, range, image);
}
/** /**
* @brief Read a range of given texture mip level to a buffer image * @brief Read a range of given texture mip level to a buffer image
* *
@ -820,6 +871,16 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
*/ */
CompressedImage3D compressedSubImage(Int level, const Range3Di& range, CompressedImage3D&& image); CompressedImage3D compressedSubImage(Int level, const Range3Di& range, CompressedImage3D&& image);
/**
* @brief Read a range of given compressed texture mip level to an image view
*
* Compared to @ref compressedSubImage(Int, const Range3Di&, CompressedImage3D&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as @p range size.
*/
void compressedSubImage(Int level, const Range3Di& range, MutableCompressedImageView3D& image);
/** /**
* @brief Read a range of given compressed texture mip level to a buffer image * @brief Read a range of given compressed texture mip level to a buffer image
* *

47
src/Magnum/GL/CubeMapTextureArray.h

@ -485,6 +485,17 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture {
*/ */
Image3D image(Int level, Image3D&& image); Image3D image(Int level, Image3D&& image);
/**
* @brief Read given texture mip level to an image view
*
* Compared to @ref image(Int, Image3D&) the function reads the pixels
* into the memory provided by @p image, expecting it's not
* @cpp nullptr @ce and its size is the same as size of given @p level.
*/
void image(Int level, MutableImageView3D& image) {
AbstractTexture::image<3>(level, image);
}
/** /**
* @brief Read given texture mip level to a buffer image * @brief Read given texture mip level to a buffer image
* *
@ -529,6 +540,18 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture {
*/ */
CompressedImage3D compressedImage(Int level, CompressedImage3D&& image); CompressedImage3D compressedImage(Int level, CompressedImage3D&& image);
/**
* @brief Read given compressed texture mip level to an image view
*
* Compared to @ref compressedImage(Int, CompressedImage3D&) the
* function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as size of given @p level.
*/
void compressedImage(Int level, MutableCompressedImageView3D& image) {
AbstractTexture::compressedImage<3>(level, image);
}
/** /**
* @brief Read given compressed texture mip level to a buffer image * @brief Read given compressed texture mip level to a buffer image
* *
@ -574,6 +597,18 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture {
*/ */
Image3D subImage(Int level, const Range3Di& range, Image3D&& image); Image3D subImage(Int level, const Range3Di& range, Image3D&& image);
/**
* @brief Read a range of given texture mip level to an image view
*
* Compared to @ref subImage(Int, const Range3Di&, Image3D&) the
* function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce and its size is the same as
* @p range size.
*/
void subImage(Int level, const Range3Di& range, MutableImageView3D& image) {
AbstractTexture::subImage<3>(level, range, image);
}
/** /**
* @brief Read a range of given texture mip level to a buffer image * @brief Read a range of given texture mip level to a buffer image
* *
@ -624,6 +659,18 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture {
*/ */
CompressedImage3D compressedSubImage(Int level, const Range3Di& range, CompressedImage3D&& image); CompressedImage3D compressedSubImage(Int level, const Range3Di& range, CompressedImage3D&& image);
/**
* @brief Read a range of given compressed texture mip level to an image view
*
* Compared to @ref compressedSubImage(Int, const Range3Di&, CompressedImage3D&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as @p range size.
*/
void compressedSubImage(Int level, const Range3Di& range, MutableCompressedImageView3D& image) {
AbstractTexture::compressedSubImage<3>(level, range, image);
}
/** /**
* @brief Read a range of given compressed texture mip level to a buffer image * @brief Read a range of given compressed texture mip level to a buffer image
* *

46
src/Magnum/GL/RectangleTexture.h

@ -369,6 +369,17 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture {
*/ */
Image2D image(Image2D&& image); Image2D image(Image2D&& image);
/**
* @brief Read texture to an image view
*
* Compared to @ref image(Image2D&) the function reads the pixels into
* the memory provided by @p image, expecting it's not @cpp nullptr @ce
* and its size is the same as texture size.
*/
void image(MutableImageView2D& image) {
AbstractTexture::image<2>(0, image);
}
/** /**
* @brief Read texture to a buffer image * @brief Read texture to a buffer image
* *
@ -407,6 +418,18 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture {
*/ */
CompressedImage2D compressedImage(CompressedImage2D&& image); CompressedImage2D compressedImage(CompressedImage2D&& image);
/**
* @brief Read compressed texture to an image view
*
* Compared to @ref compressedImage(CompressedImage2D&) the function
* reads the pixels into the memory provided by @p image, expecting
* it's not @cpp nullptr @ce, its format is the same as texture format
* and its size is the same as texture size.
*/
void compressedImage(MutableCompressedImageView2D& image) {
AbstractTexture::compressedImage<2>(0, image);
}
/** /**
* @brief Read compressed texture to a buffer image * @brief Read compressed texture to a buffer image
* *
@ -446,6 +469,17 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture {
*/ */
Image2D subImage(const Range2Di& range, Image2D&& image); Image2D subImage(const Range2Di& range, Image2D&& image);
/**
* @brief Read a range of given texture mip level to an image view
*
* Compared to @ref subImage(const Range2Di&, Image2D&) the function
* reads the pixels into the memory provided by @p image, expecting
* it's not @cpp nullptr @ce and its size is the same as @p range size.
*/
void subImage(const Range2Di& range, MutableImageView2D& image) {
AbstractTexture::subImage<2>(0, range, image);
}
/** /**
* @brief Read a texture range to a buffer image * @brief Read a texture range to a buffer image
* *
@ -490,6 +524,18 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture {
*/ */
CompressedImage2D compressedSubImage(const Range2Di& range, CompressedImage2D&& image); CompressedImage2D compressedSubImage(const Range2Di& range, CompressedImage2D&& image);
/**
* @brief Read a compressed texture range to an image view
*
* Compared to @ref compressedSubImage(const Range2Di&, CompressedImage2D&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as @p range size.
*/
void compressedSubImage(const Range2Di& range, MutableCompressedImageView2D& image) {
AbstractTexture::compressedSubImage<2>(0, range, image);
}
/** /**
* @brief Read a compressed texture range to a buffer image * @brief Read a compressed texture range to a buffer image
* *

258
src/Magnum/GL/Test/AbstractTextureGLTest.cpp

@ -23,12 +23,17 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <sstream>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include "Magnum/ImageView.h"
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/GL/PixelFormat.h"
#include "Magnum/GL/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/GL/TextureFormat.h"
#include "Magnum/GL/OpenGLTester.h" #include "Magnum/GL/OpenGLTester.h"
#include "Magnum/Math/Range.h"
namespace Magnum { namespace GL { namespace Test { namespace { namespace Magnum { namespace GL { namespace Test { namespace {
@ -38,6 +43,22 @@ struct AbstractTextureGLTest: OpenGLTester {
void construct(); void construct();
void constructMove(); void constructMove();
#ifndef MAGNUM_TARGET_GLES
void imageQueryViewNullptr();
void imageQueryViewBadSize();
void subImageQueryViewNullptr();
void subImageQueryViewBadSize();
void compressedImageQueryViewNullptr();
void compressedImageQueryViewBadSize();
void compressedImageQueryViewBadDataSize();
void compressedImageQueryViewBadFormat();
void compressedSubImageQueryViewNullptr();
void compressedSubImageQueryViewBadSize();
void compressedSubImageQueryViewBadDataSize();
void compressedSubImageQueryViewBadFormat();
#endif
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
void label(); void label();
#endif #endif
@ -47,6 +68,22 @@ AbstractTextureGLTest::AbstractTextureGLTest() {
addTests({&AbstractTextureGLTest::construct, addTests({&AbstractTextureGLTest::construct,
&AbstractTextureGLTest::constructMove, &AbstractTextureGLTest::constructMove,
#ifndef MAGNUM_TARGET_GLES
&AbstractTextureGLTest::imageQueryViewNullptr,
&AbstractTextureGLTest::imageQueryViewBadSize,
&AbstractTextureGLTest::subImageQueryViewNullptr,
&AbstractTextureGLTest::subImageQueryViewBadSize,
&AbstractTextureGLTest::compressedImageQueryViewNullptr,
&AbstractTextureGLTest::compressedImageQueryViewBadSize,
&AbstractTextureGLTest::compressedImageQueryViewBadDataSize,
&AbstractTextureGLTest::compressedImageQueryViewBadFormat,
&AbstractTextureGLTest::compressedSubImageQueryViewNullptr,
&AbstractTextureGLTest::compressedSubImageQueryViewBadSize,
&AbstractTextureGLTest::compressedSubImageQueryViewBadDataSize,
&AbstractTextureGLTest::compressedSubImageQueryViewBadFormat,
#endif
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
&AbstractTextureGLTest::label &AbstractTextureGLTest::label
#endif #endif
@ -86,6 +123,227 @@ void AbstractTextureGLTest::constructMove() {
CORRADE_COMPARE(c.id(), id); CORRADE_COMPARE(c.id(), id);
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractTextureGLTest::imageQueryViewNullptr() {
Texture2D texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableImageView2D image{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, {nullptr, 2*2*4}};
std::ostringstream out;
Error redirectError{&out};
texture.image(0, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::image(): image view is nullptr\n");
}
void AbstractTextureGLTest::imageQueryViewBadSize() {
Texture2D texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*4];
MutableImageView2D image{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2, 1}, data};
std::ostringstream out;
Error redirectError{&out};
texture.image(0, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::image(): expected image view size Vector(2, 2) but got Vector(2, 1)\n");
}
void AbstractTextureGLTest::subImageQueryViewNullptr() {
Texture2D texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableImageView2D image{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, {nullptr, 2*2*4}};
std::ostringstream out;
Error redirectError{&out};
texture.subImage(0, {{}, Vector2i{2}}, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::subImage(): image view is nullptr\n");
}
void AbstractTextureGLTest::subImageQueryViewBadSize() {
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*4];
MutableImageView2D image{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2, 1}, data};
std::ostringstream out;
Error redirectError{&out};
texture.subImage(0, {{}, Vector2i{2}}, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::subImage(): expected image view size Vector(2, 2) but got Vector(2, 1)\n");
}
void AbstractTextureGLTest::compressedImageQueryViewNullptr() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, {nullptr, 16}};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedImage(): image view is nullptr\n");
}
void AbstractTextureGLTest::compressedImageQueryViewBadSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*16];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4, 8}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedImage(): expected image view size Vector(4, 4) but got Vector(4, 8)\n");
}
void AbstractTextureGLTest::compressedImageQueryViewBadDataSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16 - 1];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedImage(): expected image view data size 16 bytes but got 15\n");
}
void AbstractTextureGLTest::compressedImageQueryViewBadFormat() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt1, Vector2i{4}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedImage(): expected image view format GL::CompressedPixelFormat::RGBAS3tcDxt3 but got GL::CompressedPixelFormat::RGBAS3tcDxt1\n");
}
void AbstractTextureGLTest::compressedSubImageQueryViewNullptr() {
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, {nullptr, 16}};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, {{}, Vector2i{4}}, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedSubImage(): image view is nullptr\n");
}
void AbstractTextureGLTest::compressedSubImageQueryViewBadSize() {
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*16];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4, 8}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, {{}, Vector2i{4}}, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedSubImage(): expected image view size Vector(4, 4) but got Vector(4, 8)\n");
}
void AbstractTextureGLTest::compressedSubImageQueryViewBadDataSize() {
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16 - 1];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, {{}, Vector2i{4}}, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedSubImage(): expected image view data size 16 bytes but got 15\n");
}
void AbstractTextureGLTest::compressedSubImageQueryViewBadFormat() {
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt1, Vector2i{4}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, {{}, Vector2i{4}}, image);
CORRADE_COMPARE(out.str(), "GL::AbstractTexture::compressedSubImage(): expected image view format GL::CompressedPixelFormat::RGBAS3tcDxt3 but got GL::CompressedPixelFormat::RGBAS3tcDxt1\n");
}
#endif
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
void AbstractTextureGLTest::label() { void AbstractTextureGLTest::label() {
/* No-Op version is tested in AbstractObjectGLTest */ /* No-Op version is tested in AbstractObjectGLTest */

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

@ -104,14 +104,14 @@ if(NOT MAGNUM_TARGET_GLES)
endif() endif()
if(BUILD_GL_TESTS) if(BUILD_GL_TESTS)
corrade_add_test(GLAbstractTextureGLTest AbstractTextureGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLAbstractTextureGLTest AbstractTextureGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib)
corrade_add_test(GLBufferGLTest BufferGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLBufferGLTest BufferGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_test(GLCubeMapTextureGLTest CubeMapTextureGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLCubeMapTextureGLTest CubeMapTextureGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib)
corrade_add_test(GLFramebufferGLTest FramebufferGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLFramebufferGLTest FramebufferGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib)
corrade_add_test(GLMeshGLTest MeshGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib) corrade_add_test(GLMeshGLTest MeshGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib)
corrade_add_test(GLRendererGLTest RendererGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLRendererGLTest RendererGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_test(GLRenderbufferGLTest RenderbufferGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLRenderbufferGLTest RenderbufferGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_test(GLTextureGLTest TextureGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLTextureGLTest TextureGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib)
corrade_add_resource(GLAbstractShaderProgramGLTest_RES AbstractShaderProgramGLTestFiles/resources.conf) corrade_add_resource(GLAbstractShaderProgramGLTest_RES AbstractShaderProgramGLTestFiles/resources.conf)
corrade_add_test(GLAbstractShaderProgramGLTest corrade_add_test(GLAbstractShaderProgramGLTest

147
src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp

@ -62,20 +62,30 @@ struct CubeMapTextureArrayGLTest: OpenGLTester {
void image(); void image();
void imageBuffer(); void imageBuffer();
#ifndef MAGNUM_TARGET_GLES
void imageQueryView();
#endif
void subImage(); void subImage();
void subImageBuffer(); void subImageBuffer();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void subImageQuery(); void subImageQuery();
void subImageQueryView();
void subImageQueryBuffer(); void subImageQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
void compressedImage(); void compressedImage();
void compressedImageBuffer(); void compressedImageBuffer();
#ifndef MAGNUM_TARGET_GLES
void compressedImageQueryView();
#endif
void compressedSubImage(); void compressedSubImage();
void compressedSubImageBuffer(); void compressedSubImageBuffer();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void compressedSubImageQuery(); void compressedSubImageQuery();
void compressedSubImageQueryView();
void compressedSubImageQueryBuffer(); void compressedSubImageQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
void generateMipmap(); void generateMipmap();
@ -274,28 +284,36 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() {
addInstancedTests({ addInstancedTests({
&CubeMapTextureArrayGLTest::image, &CubeMapTextureArrayGLTest::image,
&CubeMapTextureArrayGLTest::imageBuffer}, &CubeMapTextureArrayGLTest::imageBuffer,
Containers::arraySize(PixelStorageData)); #ifndef MAGNUM_TARGET_GLES
&CubeMapTextureArrayGLTest::imageQueryView
#endif
}, Containers::arraySize(PixelStorageData));
addInstancedTests({ addInstancedTests({
&CubeMapTextureArrayGLTest::subImage, &CubeMapTextureArrayGLTest::subImage,
&CubeMapTextureArrayGLTest::subImageBuffer, &CubeMapTextureArrayGLTest::subImageBuffer,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&CubeMapTextureArrayGLTest::subImageQuery, &CubeMapTextureArrayGLTest::subImageQuery,
&CubeMapTextureArrayGLTest::subImageQueryView,
&CubeMapTextureArrayGLTest::subImageQueryBuffer &CubeMapTextureArrayGLTest::subImageQueryBuffer
#endif #endif
}, Containers::arraySize(SubPixelStorageData)); }, Containers::arraySize(SubPixelStorageData));
addInstancedTests({ addInstancedTests({
&CubeMapTextureArrayGLTest::compressedImage, &CubeMapTextureArrayGLTest::compressedImage,
&CubeMapTextureArrayGLTest::compressedImageBuffer}, &CubeMapTextureArrayGLTest::compressedImageBuffer,
Containers::arraySize(CompressedPixelStorageData)); #ifndef MAGNUM_TARGET_GLES
&CubeMapTextureArrayGLTest::compressedImageQueryView
#endif
}, Containers::arraySize(CompressedPixelStorageData));
addInstancedTests({ addInstancedTests({
&CubeMapTextureArrayGLTest::compressedSubImage, &CubeMapTextureArrayGLTest::compressedSubImage,
&CubeMapTextureArrayGLTest::compressedSubImageBuffer, &CubeMapTextureArrayGLTest::compressedSubImageBuffer,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&CubeMapTextureArrayGLTest::compressedSubImageQuery, &CubeMapTextureArrayGLTest::compressedSubImageQuery,
&CubeMapTextureArrayGLTest::compressedSubImageQueryView,
&CubeMapTextureArrayGLTest::compressedSubImageQueryBuffer, &CubeMapTextureArrayGLTest::compressedSubImageQueryBuffer,
#endif #endif
}, Containers::arraySize(CompressedSubPixelStorageData)); }, Containers::arraySize(CompressedSubPixelStorageData));
@ -627,6 +645,34 @@ void CubeMapTextureArrayGLTest::imageBuffer() {
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void CubeMapTextureArrayGLTest::imageQueryView() {
setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
CubeMapTextureArray texture;
texture.setImage(0, TextureFormat::RGBA8, ImageView3D{
PixelStorageData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 6},
PixelStorageData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorageData[testCaseInstanceId()].offset + 2*2*6*4};
MutableImageView3D image{PixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 6}, data};
texture.image(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i(2, 2, 6));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorageData[testCaseInstanceId()].offset),
PixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
#endif
void CubeMapTextureArrayGLTest::compressedImage() { void CubeMapTextureArrayGLTest::compressedImage() {
setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name);
@ -710,6 +756,41 @@ void CubeMapTextureArrayGLTest::compressedImageBuffer() {
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void CubeMapTextureArrayGLTest::compressedImageQueryView() {
setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
CubeMapTextureArray texture;
texture.setCompressedImage(0, CompressedImageView3D{
#ifndef MAGNUM_TARGET_GLES
CompressedPixelStorageData[testCaseInstanceId()].storage,
#endif
CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 6},
CompressedPixelStorageData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorageData[testCaseInstanceId()].offset + 6*16};
MutableCompressedImageView3D image{CompressedPixelStorageData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 6}, data};
texture.compressedImage(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 6}));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorageData[testCaseInstanceId()].offset),
CompressedPixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
#endif
constexpr UnsignedByte Zero[4*4*4*6]{}; constexpr UnsignedByte Zero[4*4*4*6]{};
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
constexpr UnsignedByte SubDataComplete[]{ constexpr UnsignedByte SubDataComplete[]{
@ -841,6 +922,32 @@ void CubeMapTextureArrayGLTest::subImageQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void CubeMapTextureArrayGLTest::subImageQueryView() {
setTestCaseDescription(SubPixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
CubeMapTextureArray texture;
texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 6})
.setSubImage(0, {}, ImageView3D{PixelFormat::RGBA, PixelType::UnsignedByte, {4, 4, 6}, SubDataComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{SubPixelStorageData[testCaseInstanceId()].offset + 2*2*4*4};
MutableImageView3D image{PixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 4}, data};
texture.subImage(0, Range3Di::fromSize(Vector3i{1}, {2, 2, 4}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i(2, 2, 4));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(SubPixelStorageData[testCaseInstanceId()].offset),
SubPixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void CubeMapTextureArrayGLTest::subImageQueryBuffer() { void CubeMapTextureArrayGLTest::subImageQueryBuffer() {
setTestCaseDescription(SubPixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(SubPixelStorageData[testCaseInstanceId()].name);
@ -1058,6 +1165,38 @@ void CubeMapTextureArrayGLTest::compressedSubImageQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void CubeMapTextureArrayGLTest::compressedSubImageQueryView() {
setTestCaseDescription(CompressedSubPixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedSubPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
if(CompressedSubPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
CubeMapTextureArray texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 12, 6})
.setCompressedSubImage(0, {}, CompressedImageView3D{CompressedPixelFormat::RGBAS3tcDxt3, {12, 12, 6}, CompressedSubDataComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedSubPixelStorageData[testCaseInstanceId()].offset + 4*16};
MutableCompressedImageView3D image{CompressedPixelStorageData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 4}, data};
texture.compressedSubImage(0, Range3Di::fromSize({4, 4, 1}, Vector3i{4}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i{4});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedSubPixelStorageData[testCaseInstanceId()].offset),
CompressedSubPixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void CubeMapTextureArrayGLTest::compressedSubImageQueryBuffer() { void CubeMapTextureArrayGLTest::compressedSubImageQueryBuffer() {
setTestCaseDescription(CompressedSubPixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(CompressedSubPixelStorageData[testCaseInstanceId()].name);

542
src/Magnum/GL/Test/CubeMapTextureGLTest.cpp

@ -23,7 +23,9 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <sstream>
#include <Corrade/TestSuite/Compare/Container.h> #include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/Image.h" #include "Magnum/Image.h"
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
@ -80,12 +82,20 @@ struct CubeMapTextureGLTest: OpenGLTester {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void imageBuffer(); void imageBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void imageQueryView();
void imageQueryViewNullptr();
void imageQueryViewBadSize();
#endif
void subImage(); void subImage();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void subImageBuffer(); void subImageBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void subImageQuery(); void subImageQuery();
void subImageQueryView();
/* unlike all others, subImage() simply calls into AbstractTexture, so
all assertions are already tested in AbstractTextureGLTest */
void subImageQueryBuffer(); void subImageQueryBuffer();
#endif #endif
@ -93,6 +103,13 @@ struct CubeMapTextureGLTest: OpenGLTester {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void compressedImageBuffer(); void compressedImageBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void compressedImageQueryView();
void compressedImageQueryViewNullptr();
void compressedImageQueryViewBadSize();
void compressedImageQueryViewBadDataSize();
void compressedImageQueryViewBadFormat();
#endif
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
void immutableCompressedImage(); void immutableCompressedImage();
#endif #endif
@ -102,14 +119,27 @@ struct CubeMapTextureGLTest: OpenGLTester {
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void compressedSubImageQuery(); void compressedSubImageQuery();
void compressedSubImageQueryView();
void compressedSubImageQueryViewNullptr();
void compressedSubImageQueryViewBadSize();
void compressedSubImageQueryViewBadDataSize();
void compressedSubImageQueryViewBadFormat();
void compressedSubImageQueryBuffer(); void compressedSubImageQueryBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void fullImageQuery(); void fullImageQuery();
void fullImageQueryView();
void fullImageQueryViewNullptr();
void fullImageQueryViewBadSize();
void fullImageQueryBuffer(); void fullImageQueryBuffer();
void compressedFullImageQuery(); void compressedFullImageQuery();
void compressedFullImageQueryView();
void compressedFullImageQueryViewNullptr();
void compressedFullImageQueryViewBadSize();
void compressedFullImageQueryViewBadDataSize();
void compressedFullImageQueryViewBadFormat();
void compressedFullImageQueryBuffer(); void compressedFullImageQueryBuffer();
#endif #endif
@ -306,13 +336,25 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&CubeMapTextureGLTest::imageBuffer, &CubeMapTextureGLTest::imageBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES
&CubeMapTextureGLTest::imageQueryView,
#endif
}, Containers::arraySize(PixelStorageData)); }, Containers::arraySize(PixelStorageData));
#ifndef MAGNUM_TARGET_GLES
addTests({&CubeMapTextureGLTest::imageQueryViewNullptr,
&CubeMapTextureGLTest::imageQueryViewBadSize});
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
addInstancedTests({ addInstancedTests({
&CubeMapTextureGLTest::fullImageQuery, &CubeMapTextureGLTest::fullImageQuery,
&CubeMapTextureGLTest::fullImageQueryView,
&CubeMapTextureGLTest::fullImageQueryBuffer}, &CubeMapTextureGLTest::fullImageQueryBuffer},
Containers::arraySize(FullPixelStorageData)); Containers::arraySize(FullPixelStorageData));
addTests({&CubeMapTextureGLTest::fullImageQueryViewNullptr,
&CubeMapTextureGLTest::fullImageQueryViewBadSize});
#endif #endif
addInstancedTests({ addInstancedTests({
@ -322,6 +364,7 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() {
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&CubeMapTextureGLTest::subImageQuery, &CubeMapTextureGLTest::subImageQuery,
&CubeMapTextureGLTest::subImageQueryView,
&CubeMapTextureGLTest::subImageQueryBuffer &CubeMapTextureGLTest::subImageQueryBuffer
#endif #endif
}, Containers::arraySize(PixelStorageData)); }, Containers::arraySize(PixelStorageData));
@ -331,16 +374,30 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&CubeMapTextureGLTest::compressedImageBuffer, &CubeMapTextureGLTest::compressedImageBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES
&CubeMapTextureGLTest::compressedImageQueryView,
#endif
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
&CubeMapTextureGLTest::immutableCompressedImage, &CubeMapTextureGLTest::immutableCompressedImage,
#endif #endif
}, Containers::arraySize(CompressedPixelStorageData)); }, Containers::arraySize(CompressedPixelStorageData));
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
addTests({&CubeMapTextureGLTest::compressedImageQueryViewNullptr,
&CubeMapTextureGLTest::compressedImageQueryViewBadSize,
&CubeMapTextureGLTest::compressedImageQueryViewBadDataSize,
&CubeMapTextureGLTest::compressedImageQueryViewBadFormat});
addInstancedTests({ addInstancedTests({
&CubeMapTextureGLTest::compressedFullImageQuery, &CubeMapTextureGLTest::compressedFullImageQuery,
&CubeMapTextureGLTest::compressedFullImageQueryView,
&CubeMapTextureGLTest::compressedFullImageQueryBuffer}, &CubeMapTextureGLTest::compressedFullImageQueryBuffer},
Containers::arraySize(CompressedFullPixelStorageData)); Containers::arraySize(CompressedFullPixelStorageData));
addTests({&CubeMapTextureGLTest::compressedFullImageQueryViewNullptr,
&CubeMapTextureGLTest::compressedFullImageQueryViewBadSize,
&CubeMapTextureGLTest::compressedFullImageQueryViewBadDataSize,
&CubeMapTextureGLTest::compressedFullImageQueryViewBadFormat});
#endif #endif
addInstancedTests({ addInstancedTests({
@ -350,10 +407,18 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() {
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&CubeMapTextureGLTest::compressedSubImageQuery, &CubeMapTextureGLTest::compressedSubImageQuery,
&CubeMapTextureGLTest::compressedSubImageQueryView,
&CubeMapTextureGLTest::compressedSubImageQueryBuffer &CubeMapTextureGLTest::compressedSubImageQueryBuffer
#endif #endif
}, Containers::arraySize(CompressedPixelStorageData)); }, Containers::arraySize(CompressedPixelStorageData));
#ifndef MAGNUM_TARGET_GLES
addTests({&CubeMapTextureGLTest::compressedSubImageQueryViewNullptr,
&CubeMapTextureGLTest::compressedSubImageQueryViewBadSize,
&CubeMapTextureGLTest::compressedSubImageQueryViewBadDataSize,
&CubeMapTextureGLTest::compressedSubImageQueryViewBadFormat});
#endif
addTests({&CubeMapTextureGLTest::generateMipmap, addTests({&CubeMapTextureGLTest::generateMipmap,
&CubeMapTextureGLTest::invalidateImage, &CubeMapTextureGLTest::invalidateImage,
@ -807,6 +872,64 @@ void CubeMapTextureGLTest::imageBuffer() {
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void CubeMapTextureGLTest::imageQueryView() {
setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name);
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2})
.setSubImage(CubeMapCoordinate::PositiveY, 0, {},
ImageView2D{PixelStorageData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i(2),
PixelStorageData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorageData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView2D image{PixelStorageData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, data};
texture.image(CubeMapCoordinate::PositiveY, 0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i(2));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorageData[testCaseInstanceId()].offset),
PixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void CubeMapTextureGLTest::imageQueryViewNullptr() {
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableImageView2D image{PixelFormat::RGBA, PixelType::UnsignedByte,
Vector2i{2}, {nullptr, 2*2*4}};
std::ostringstream out;
Error redirectError{&out};
texture.image(CubeMapCoordinate::PositiveY, 0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::image(): image view is nullptr\n");
}
void CubeMapTextureGLTest::imageQueryViewBadSize() {
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*4];
MutableImageView2D image{PixelFormat::RGBA, PixelType::UnsignedByte,
{2, 1}, data};
std::ostringstream out;
Error redirectError{&out};
texture.image(CubeMapCoordinate::PositiveY, 0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::image(): expected image view size Vector(2, 2) but got Vector(2, 1)\n");
}
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
constexpr UnsignedByte SubDataComplete[]{ constexpr UnsignedByte SubDataComplete[]{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -932,6 +1055,31 @@ void CubeMapTextureGLTest::subImageQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void CubeMapTextureGLTest::subImageQueryView() {
setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4})
.setSubImage(CubeMapCoordinate::PositiveX, 0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, {4, 4}, SubDataComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorageData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView3D image{PixelStorageData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 1}, data};
texture.subImage(0, Range3Di::fromSize({1, 1, 0}, {2, 2, 1}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i(2, 2, 1));
CORRADE_COMPARE_AS(Containers::arrayCast<const UnsignedByte>(image.data()).suffix(PixelStorageData[testCaseInstanceId()].offset),
PixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void CubeMapTextureGLTest::subImageQueryBuffer() { void CubeMapTextureGLTest::subImageQueryBuffer() {
setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name);
@ -1053,6 +1201,111 @@ void CubeMapTextureGLTest::compressedImageBuffer() {
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void CubeMapTextureGLTest::compressedImageQueryView() {
setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
const CompressedImageView2D view{
CompressedPixelStorageData[testCaseInstanceId()].storage,
CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4},
CompressedPixelStorageData[testCaseInstanceId()].dataSparse};
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4})
.setCompressedSubImage(CubeMapCoordinate::PositiveZ, 0, {}, view);
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorageData[testCaseInstanceId()].offset + 16};
MutableCompressedImageView2D image{CompressedPixelStorageData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, data};
texture.compressedImage(CubeMapCoordinate::PositiveZ, 0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i{4});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorageData[testCaseInstanceId()].offset),
CompressedPixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void CubeMapTextureGLTest::compressedImageQueryViewNullptr() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, {nullptr, 16}};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(CubeMapCoordinate::PositiveX, 0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): image view is nullptr\n");
}
void CubeMapTextureGLTest::compressedImageQueryViewBadSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*16];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4, 8}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(CubeMapCoordinate::PositiveX, 0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view size Vector(4, 4) but got Vector(4, 8)\n");
}
void CubeMapTextureGLTest::compressedImageQueryViewBadDataSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16 - 1];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(CubeMapCoordinate::PositiveX, 0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view data size 16 bytes but got 15\n");
}
void CubeMapTextureGLTest::compressedImageQueryViewBadFormat() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16];
MutableCompressedImageView2D image{CompressedPixelFormat::RGBAS3tcDxt1, Vector2i{4}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(CubeMapCoordinate::PositiveX, 0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view format GL::CompressedPixelFormat::RGBAS3tcDxt3 but got GL::CompressedPixelFormat::RGBAS3tcDxt1\n");
}
#endif
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
void CubeMapTextureGLTest::immutableCompressedImage() { void CubeMapTextureGLTest::immutableCompressedImage() {
setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name);
@ -1284,6 +1537,107 @@ void CubeMapTextureGLTest::compressedSubImageQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void CubeMapTextureGLTest::compressedSubImageQueryView() {
setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
if(CompressedPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12})
.setCompressedSubImage(CubeMapCoordinate::PositiveX, 0, {}, CompressedImageView2D{CompressedPixelFormat::RGBAS3tcDxt3, {12, 12}, CompressedSubDataComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorageData[testCaseInstanceId()].offset + 16};
MutableCompressedImageView3D image{CompressedPixelStorageData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 1}, data};
texture.compressedSubImage(0, Range3Di::fromSize({4, 4, 0}, {4, 4, 1}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 1}));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorageData[testCaseInstanceId()].offset),
CompressedPixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void CubeMapTextureGLTest::compressedSubImageQueryViewNullptr() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector3i{4, 4, 1}, {nullptr, 16}};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, Range3Di::fromSize({4, 4, 0}, {4, 4, 1}), image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedSubImage(): image view is nullptr\n");
}
void CubeMapTextureGLTest::compressedSubImageQueryViewBadSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*16];
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector3i{4, 4, 2}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, Range3Di::fromSize({4, 4, 0}, {4, 4, 1}), image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedSubImage(): expected image view size Vector(4, 4, 1) but got Vector(4, 4, 2)\n");
}
void CubeMapTextureGLTest::compressedSubImageQueryViewBadDataSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16 - 1];
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector3i{4, 4, 1}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, Range3Di::fromSize({4, 4, 0}, {4, 4, 1}), image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedSubImage(): expected image view data size 16 bytes but got 15\n");
}
void CubeMapTextureGLTest::compressedSubImageQueryViewBadFormat() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16];
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt1, Vector3i{4, 4, 1}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedSubImage(0, Range3Di::fromSize({4, 4, 0}, {4, 4, 1}), image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedSubImage(): expected image view format GL::CompressedPixelFormat::RGBAS3tcDxt3 but got GL::CompressedPixelFormat::RGBAS3tcDxt1\n");
}
void CubeMapTextureGLTest::compressedSubImageQueryBuffer() { void CubeMapTextureGLTest::compressedSubImageQueryBuffer() {
setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name);
@ -1356,6 +1710,78 @@ void CubeMapTextureGLTest::fullImageQuery() {
} }
} }
void CubeMapTextureGLTest::fullImageQueryView() {
setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::direct_state_access>())
CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2, 2})
.setSubImage(0, {}, ImageView3D{
PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 6},
FullPixelStorageData[testCaseInstanceId()].data});
{
#ifdef CORRADE_TARGET_WINDOWS
bool fails(Context::current().detectedDriver() & Context::DetectedDriver::IntelWindows);
CORRADE_EXPECT_FAIL_IF(fails,
"ARB_DSA cubemap APIs are broken on Intel Windows drivers.");
#endif
MAGNUM_VERIFY_NO_GL_ERROR();
#ifdef CORRADE_TARGET_WINDOWS
if(fails) CORRADE_SKIP("Skipping the rest of the test");
#endif
}
Containers::Array<char> data{FullPixelStorageData[testCaseInstanceId()].offset + 2*2*6*4};
MutableImageView3D image{FullPixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 6}, data};
texture.image(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i(2, 2, 6));
{
CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && FullPixelStorageData[testCaseInstanceId()].storage != PixelStorage{},
"Mesa drivers can't handle non-default pixel storage for full cubemap image queries.");
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(FullPixelStorageData[testCaseInstanceId()].offset),
FullPixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
}
void CubeMapTextureGLTest::fullImageQueryViewNullptr() {
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableImageView3D image{PixelFormat::RGBA, PixelType::UnsignedByte,
{2, 2, 6}, {nullptr, 2*2*6*4}};
std::ostringstream out;
Error redirectError{&out};
texture.image(0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::image(): image view is nullptr\n");
}
void CubeMapTextureGLTest::fullImageQueryViewBadSize() {
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*4*6];
MutableImageView3D image{PixelFormat::RGBA, PixelType::UnsignedByte,
{2, 1, 6}, data};
std::ostringstream out;
Error redirectError{&out};
texture.image(0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::image(): expected image view size Vector(2, 2, 6) but got Vector(2, 1, 6)\n");
}
void CubeMapTextureGLTest::fullImageQueryBuffer() { void CubeMapTextureGLTest::fullImageQueryBuffer() {
setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name);
@ -1441,6 +1867,122 @@ void CubeMapTextureGLTest::compressedFullImageQuery() {
} }
} }
void CubeMapTextureGLTest::compressedFullImageQueryView() {
setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::direct_state_access>())
CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4})
.setCompressedSubImage(0, {}, CompressedImageView3D{
CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 6},
CompressedFullPixelStorageData[testCaseInstanceId()].data});
{
#ifdef CORRADE_TARGET_WINDOWS
bool fails(Context::current().detectedDriver() & Context::DetectedDriver::IntelWindows);
CORRADE_EXPECT_FAIL_IF(fails,
"ARB_DSA cubemap APIs are broken on Intel Windows drivers.");
#endif
MAGNUM_VERIFY_NO_GL_ERROR();
#ifdef CORRADE_TARGET_WINDOWS
if(fails) CORRADE_SKIP("Skipping the rest of the test");
#endif
}
Containers::Array<char> data{CompressedFullPixelStorageData[testCaseInstanceId()].offset + 16*6};
MutableCompressedImageView3D image{CompressedFullPixelStorageData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 6}, data};
texture.compressedImage(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 6}));
{
CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && CompressedFullPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{},
"Mesa drivers can't handle non-default pixel storage for full cubemap image queries.");
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedFullPixelStorageData[testCaseInstanceId()].offset),
CompressedFullPixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
}
void CubeMapTextureGLTest::compressedFullImageQueryViewNullptr() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector3i{4, 4, 6}, {nullptr, 16*6}};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): image view is nullptr\n");
}
void CubeMapTextureGLTest::compressedFullImageQueryViewBadSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[2*6*16];
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector3i{4, 8, 6}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view size Vector(4, 4, 6) but got Vector(4, 8, 6)\n");
}
void CubeMapTextureGLTest::compressedFullImageQueryViewBadDataSize() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[16*6 - 1];
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt3, Vector3i{4, 4, 6}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view data size 96 bytes but got 95\n");
}
void CubeMapTextureGLTest::compressedFullImageQueryViewBadFormat() {
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4});
MAGNUM_VERIFY_NO_GL_ERROR();
char data[6*16];
MutableCompressedImageView3D image{CompressedPixelFormat::RGBAS3tcDxt1, Vector3i{4, 4, 6}, data};
std::ostringstream out;
Error redirectError{&out};
texture.compressedImage(0, image);
CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view format GL::CompressedPixelFormat::RGBAS3tcDxt3 but got GL::CompressedPixelFormat::RGBAS3tcDxt1\n");
}
void CubeMapTextureGLTest::compressedFullImageQueryBuffer() { void CubeMapTextureGLTest::compressedFullImageQueryBuffer() {
setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name);

104
src/Magnum/GL/Test/FramebufferGLTest.cpp

@ -23,6 +23,7 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <sstream>
#include <Corrade/TestSuite/Compare/Container.h> #include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
@ -124,6 +125,9 @@ struct FramebufferGLTest: OpenGLTester {
void invalidateSub(); void invalidateSub();
#endif #endif
void read(); void read();
void readView();
void readViewNullptr();
void readViewBadSize();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void readBuffer(); void readBuffer();
#endif #endif
@ -263,6 +267,9 @@ FramebufferGLTest::FramebufferGLTest() {
&FramebufferGLTest::invalidateSub, &FramebufferGLTest::invalidateSub,
#endif #endif
&FramebufferGLTest::read, &FramebufferGLTest::read,
&FramebufferGLTest::readView,
&FramebufferGLTest::readViewNullptr,
&FramebufferGLTest::readViewBadSize,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&FramebufferGLTest::readBuffer, &FramebufferGLTest::readBuffer,
#endif #endif
@ -1528,6 +1535,103 @@ void FramebufferGLTest::read() {
#endif #endif
} }
void FramebufferGLTest::readView() {
using namespace Math::Literals;
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::framebuffer_object>())
CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available."));
#endif
Renderbuffer color;
#ifndef MAGNUM_TARGET_GLES2
color.setStorage(RenderbufferFormat::RGBA8, Vector2i(128));
#else
color.setStorage(RenderbufferFormat::RGBA4, Vector2i(128));
#endif
Framebuffer framebuffer({{}, Vector2i(128)});
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), color);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete);
CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete);
#ifndef MAGNUM_TARGET_GLES2
Renderer::setClearColor(0x80402011_rgbaf);
#else
/* Using only RGBA4, supply less precision. This has to be one on the input
because SwiftShader stores RGBA4 as RGBA8 internally, thus preserving
the full precision of the input. */
Renderer::setClearColor(0x88442211_rgbaf);
#endif
Renderer::setClearDepth(Math::unpack<Float, UnsignedShort>(48352));
Renderer::setClearStencil(67);
framebuffer.clear(FramebufferClear::Color);
char data[(DataOffset + 8*16)*sizeof(Color4ub)]{};
MutableImageView2D view{DataStorage, PixelFormat::RGBA, PixelType::UnsignedByte, {8, 16}, data};
framebuffer.read(Range2Di::fromSize({16, 8}, {8, 16}), view);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(view.size(), Vector2i(8, 16));
CORRADE_COMPARE(view.data().size(), (DataOffset + 8*16)*sizeof(Color4ub));
#ifndef MAGNUM_TARGET_GLES2
CORRADE_COMPARE(Containers::arrayCast<Color4ub>(view.data())[DataOffset], 0x80402011_rgba);
#else /* using only RGBA4, less precision */
CORRADE_COMPARE(Containers::arrayCast<Color4ub>(view.data())[DataOffset], 0x88442211_rgba);
#endif
}
void FramebufferGLTest::readViewNullptr() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::framebuffer_object>())
CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available."));
#endif
Renderbuffer color;
#ifndef MAGNUM_TARGET_GLES2
color.setStorage(RenderbufferFormat::RGBA8, Vector2i(128));
#else
color.setStorage(RenderbufferFormat::RGBA4, Vector2i(128));
#endif
Framebuffer framebuffer({{}, Vector2i(128)});
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), color);
MutableImageView2D view{DataStorage, PixelFormat::RGBA, PixelType::UnsignedByte, {8, 16}, {nullptr, (DataOffset + 8*15)*sizeof(Color4ub)}};
std::ostringstream out;
Error redirectError{&out};
framebuffer.read({{}, {8, 16}}, view);
CORRADE_COMPARE(out.str(), "GL::AbstractFramebuffer::read(): image view is nullptr\n");
}
void FramebufferGLTest::readViewBadSize() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::framebuffer_object>())
CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available."));
#endif
Renderbuffer color;
#ifndef MAGNUM_TARGET_GLES2
color.setStorage(RenderbufferFormat::RGBA8, Vector2i(128));
#else
color.setStorage(RenderbufferFormat::RGBA4, Vector2i(128));
#endif
Framebuffer framebuffer({{}, Vector2i(128)});
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), color);
char data[(DataOffset + 8*15)*sizeof(Color4ub)]{};
MutableImageView2D view{DataStorage, PixelFormat::RGBA, PixelType::UnsignedByte, {8, 15}, data};
std::ostringstream out;
Error redirectError{&out};
framebuffer.read({{}, {8, 16}}, view);
CORRADE_COMPARE(out.str(), "GL::AbstractFramebuffer::read(): expected image view size Vector(8, 16) but got Vector(8, 15)\n");
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void FramebufferGLTest::readBuffer() { void FramebufferGLTest::readBuffer() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

70
src/Magnum/GL/Test/RectangleTextureGLTest.cpp

@ -60,17 +60,23 @@ struct RectangleTextureGLTest: OpenGLTester {
void image(); void image();
void imageBuffer(); void imageBuffer();
void imageQueryView();
void subImage(); void subImage();
void subImageBuffer(); void subImageBuffer();
void subImageQuery(); void subImageQuery();
void subImageQueryView();
void subImageQueryBuffer(); void subImageQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
void compressedImage(); void compressedImage();
void compressedImageBuffer(); void compressedImageBuffer();
void compressedImageQueryView();
void compressedSubImage(); void compressedSubImage();
void compressedSubImageBuffer(); void compressedSubImageBuffer();
void compressedSubImageQuery(); void compressedSubImageQuery();
void compressedSubImageQueryView();
void compressedSubImageQueryBuffer(); void compressedSubImageQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
void invalidateImage(); void invalidateImage();
void invalidateSubImage(); void invalidateSubImage();
@ -126,17 +132,21 @@ RectangleTextureGLTest::RectangleTextureGLTest() {
addInstancedTests({ addInstancedTests({
&RectangleTextureGLTest::image, &RectangleTextureGLTest::image,
&RectangleTextureGLTest::imageBuffer, &RectangleTextureGLTest::imageBuffer,
&RectangleTextureGLTest::imageQueryView,
&RectangleTextureGLTest::subImage, &RectangleTextureGLTest::subImage,
&RectangleTextureGLTest::subImageBuffer, &RectangleTextureGLTest::subImageBuffer,
&RectangleTextureGLTest::subImageQuery, &RectangleTextureGLTest::subImageQuery,
&RectangleTextureGLTest::subImageQueryView,
&RectangleTextureGLTest::subImageQueryBuffer}, &RectangleTextureGLTest::subImageQueryBuffer},
Containers::arraySize(PixelStorageData)); Containers::arraySize(PixelStorageData));
addTests({&RectangleTextureGLTest::compressedImage, addTests({&RectangleTextureGLTest::compressedImage,
&RectangleTextureGLTest::compressedImageBuffer, &RectangleTextureGLTest::compressedImageBuffer,
&RectangleTextureGLTest::compressedImageQueryView,
&RectangleTextureGLTest::compressedSubImage, &RectangleTextureGLTest::compressedSubImage,
&RectangleTextureGLTest::compressedSubImageBuffer, &RectangleTextureGLTest::compressedSubImageBuffer,
&RectangleTextureGLTest::compressedSubImageQuery, &RectangleTextureGLTest::compressedSubImageQuery,
&RectangleTextureGLTest::compressedSubImageQueryView,
&RectangleTextureGLTest::compressedSubImageQueryBuffer, &RectangleTextureGLTest::compressedSubImageQueryBuffer,
&RectangleTextureGLTest::invalidateImage, &RectangleTextureGLTest::invalidateImage,
@ -359,6 +369,32 @@ void RectangleTextureGLTest::imageBuffer() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void RectangleTextureGLTest::imageQueryView() {
setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_rectangle>())
CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported."));
RectangleTexture texture;
texture.setImage(TextureFormat::RGBA8, ImageView2D{
PixelStorageData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i(2),
PixelStorageData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorageData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView2D image{PixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, data};
texture.image(image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i(2));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorageData[testCaseInstanceId()].offset),
PixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
constexpr UnsignedByte Zero[4*4*4]{}; constexpr UnsignedByte Zero[4*4*4]{};
constexpr UnsignedByte SubDataComplete[]{ constexpr UnsignedByte SubDataComplete[]{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -446,6 +482,32 @@ void RectangleTextureGLTest::subImageQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void RectangleTextureGLTest::subImageQueryView() {
setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_rectangle>())
CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
RectangleTexture texture;
texture.setStorage(TextureFormat::RGBA8, Vector2i{4})
.setSubImage({}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, SubDataComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorageData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView2D image{PixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, data};
texture.subImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i{2});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorageData[testCaseInstanceId()].offset),
PixelStorageData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void RectangleTextureGLTest::subImageQueryBuffer() { void RectangleTextureGLTest::subImageQueryBuffer() {
setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name);
@ -481,6 +543,10 @@ void RectangleTextureGLTest::compressedImageBuffer() {
CORRADE_SKIP("No rectangle texture compression format exists."); CORRADE_SKIP("No rectangle texture compression format exists.");
} }
void RectangleTextureGLTest::compressedImageQueryView() {
CORRADE_SKIP("No rectangle texture compression format exists.");
}
void RectangleTextureGLTest::compressedSubImage() { void RectangleTextureGLTest::compressedSubImage() {
CORRADE_SKIP("No rectangle texture compression format exists."); CORRADE_SKIP("No rectangle texture compression format exists.");
} }
@ -493,6 +559,10 @@ void RectangleTextureGLTest::compressedSubImageQuery() {
CORRADE_SKIP("No rectangle texture compression format exists."); CORRADE_SKIP("No rectangle texture compression format exists.");
} }
void RectangleTextureGLTest::compressedSubImageQueryView() {
CORRADE_SKIP("No rectangle texture compression format exists.");
}
void RectangleTextureGLTest::compressedSubImageQueryBuffer() { void RectangleTextureGLTest::compressedSubImageQueryBuffer() {
CORRADE_SKIP("No rectangle texture compression format exists."); CORRADE_SKIP("No rectangle texture compression format exists.");
} }

211
src/Magnum/GL/Test/TextureArrayGLTest.cpp

@ -111,35 +111,51 @@ struct TextureArrayGLTest: OpenGLTester {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void image1D(); void image1D();
void image1DBuffer(); void image1DBuffer();
void image1DQueryView();
void subImage1D(); void subImage1D();
void subImage1DBuffer(); void subImage1DBuffer();
void subImage1DQuery(); void subImage1DQuery();
void subImage1DQueryView();
void subImage1DQueryBuffer(); void subImage1DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
void compressedImage1D(); void compressedImage1D();
void compressedImage1DBuffer(); void compressedImage1DBuffer();
void compressedImage1DQueryView();
void compressedSubImage1D(); void compressedSubImage1D();
void compressedSubImage1DBuffer(); void compressedSubImage1DBuffer();
void compressedSubImage1DQuery(); void compressedSubImage1DQuery();
void compressedSubImage1DQueryView();
void compressedSubImage1DQueryBuffer(); void compressedSubImage1DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
void image2D(); void image2D();
void image2DBuffer(); void image2DBuffer();
#ifndef MAGNUM_TARGET_GLES
void image2DQueryView();
#endif
void subImage2D(); void subImage2D();
void subImage2DBuffer(); void subImage2DBuffer();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void subImage2DQuery(); void subImage2DQuery();
void subImage2DQueryView();
void subImage2DQueryBuffer(); void subImage2DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
void compressedImage2D(); void compressedImage2D();
void compressedImage2DBuffer(); void compressedImage2DBuffer();
#ifndef MAGNUM_TARGET_GLES
void compressedImage2DQueryView();
#endif
void compressedSubImage2D(); void compressedSubImage2D();
void compressedSubImage2DBuffer(); void compressedSubImage2DBuffer();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void compressedSubImage2DQuery(); void compressedSubImage2DQuery();
void compressedSubImage2DQueryView();
void compressedSubImage2DQueryBuffer(); void compressedSubImage2DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -320,27 +336,35 @@ TextureArrayGLTest::TextureArrayGLTest() {
addInstancedTests({ addInstancedTests({
&TextureArrayGLTest::image1D, &TextureArrayGLTest::image1D,
&TextureArrayGLTest::image1DBuffer, &TextureArrayGLTest::image1DBuffer,
&TextureArrayGLTest::image1DQueryView,
&TextureArrayGLTest::subImage1D, &TextureArrayGLTest::subImage1D,
&TextureArrayGLTest::subImage1DBuffer, &TextureArrayGLTest::subImage1DBuffer,
&TextureArrayGLTest::subImage1DQuery, &TextureArrayGLTest::subImage1DQuery,
&TextureArrayGLTest::subImage1DQueryView,
&TextureArrayGLTest::subImage1DQueryBuffer}, &TextureArrayGLTest::subImage1DQueryBuffer},
Containers::arraySize(PixelStorage1DData)); Containers::arraySize(PixelStorage1DData));
addTests({&TextureArrayGLTest::compressedImage1D, addTests({&TextureArrayGLTest::compressedImage1D,
&TextureArrayGLTest::compressedImage1DBuffer, &TextureArrayGLTest::compressedImage1DBuffer,
&TextureArrayGLTest::compressedImage1DQueryView,
&TextureArrayGLTest::compressedSubImage1D, &TextureArrayGLTest::compressedSubImage1D,
&TextureArrayGLTest::compressedSubImage1DBuffer, &TextureArrayGLTest::compressedSubImage1DBuffer,
&TextureArrayGLTest::compressedSubImage1DQuery, &TextureArrayGLTest::compressedSubImage1DQuery,
&TextureArrayGLTest::compressedSubImage1DQueryView,
&TextureArrayGLTest::compressedSubImage1DQueryBuffer}); &TextureArrayGLTest::compressedSubImage1DQueryBuffer});
#endif #endif
addInstancedTests({ addInstancedTests({
&TextureArrayGLTest::image2D, &TextureArrayGLTest::image2D,
&TextureArrayGLTest::image2DBuffer, &TextureArrayGLTest::image2DBuffer,
#ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::image2DQueryView,
#endif
&TextureArrayGLTest::subImage2D, &TextureArrayGLTest::subImage2D,
&TextureArrayGLTest::subImage2DBuffer, &TextureArrayGLTest::subImage2DBuffer,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::subImage2DQuery, &TextureArrayGLTest::subImage2DQuery,
&TextureArrayGLTest::subImage2DQueryView,
&TextureArrayGLTest::subImage2DQueryBuffer &TextureArrayGLTest::subImage2DQueryBuffer
#endif #endif
}, Containers::arraySize(PixelStorage2DData)); }, Containers::arraySize(PixelStorage2DData));
@ -348,10 +372,14 @@ TextureArrayGLTest::TextureArrayGLTest() {
addInstancedTests({ addInstancedTests({
&TextureArrayGLTest::compressedImage2D, &TextureArrayGLTest::compressedImage2D,
&TextureArrayGLTest::compressedImage2DBuffer, &TextureArrayGLTest::compressedImage2DBuffer,
#ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::compressedImage2DQueryView,
#endif
&TextureArrayGLTest::compressedSubImage2D, &TextureArrayGLTest::compressedSubImage2D,
&TextureArrayGLTest::compressedSubImage2DBuffer, &TextureArrayGLTest::compressedSubImage2DBuffer,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::compressedSubImage2DQuery, &TextureArrayGLTest::compressedSubImage2DQuery,
&TextureArrayGLTest::compressedSubImage2DQueryView,
&TextureArrayGLTest::compressedSubImage2DQueryBuffer &TextureArrayGLTest::compressedSubImage2DQueryBuffer
#endif #endif
}, Containers::arraySize(CompressedPixelStorage2DData)); }, Containers::arraySize(CompressedPixelStorage2DData));
@ -882,6 +910,32 @@ void TextureArrayGLTest::image1DBuffer() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureArrayGLTest::image1DQueryView() {
setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_array>())
CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported."));
Texture1DArray texture;
texture.setImage(0, TextureFormat::RGBA8, ImageView2D{
PixelStorage1DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i(2), PixelStorage1DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage1DData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView2D image{PixelStorage1DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, data};
texture.image(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i(2));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage1DData[testCaseInstanceId()].offset),
PixelStorage1DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
constexpr UnsignedByte Zero1D[4*4*4] = {}; constexpr UnsignedByte Zero1D[4*4*4] = {};
constexpr UnsignedByte SubData1DComplete[] = { constexpr UnsignedByte SubData1DComplete[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -969,6 +1023,33 @@ void TextureArrayGLTest::subImage1DQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureArrayGLTest::subImage1DQueryView() {
setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_array>())
CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
Texture1DArray texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4})
.setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, SubData1DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage1DData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView2D image{PixelStorage1DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, data};
texture.subImage(0, Range2Di::fromSize(Vector2i{1}, Vector2i{2}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i{2});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage1DData[testCaseInstanceId()].offset),
PixelStorage1DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void TextureArrayGLTest::subImage1DQueryBuffer() { void TextureArrayGLTest::subImage1DQueryBuffer() {
setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name);
@ -1006,6 +1087,10 @@ void TextureArrayGLTest::compressedImage1DBuffer() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
void TextureArrayGLTest::compressedImage1DQueryView() {
CORRADE_SKIP("No 1D texture compression format exists.");
}
void TextureArrayGLTest::compressedSubImage1D() { void TextureArrayGLTest::compressedSubImage1D() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
@ -1018,6 +1103,10 @@ void TextureArrayGLTest::compressedSubImage1DQuery() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
void TextureArrayGLTest::compressedSubImage1DQueryView() {
CORRADE_SKIP("No 1D texture compression format exists.");
}
void TextureArrayGLTest::compressedSubImage1DQueryBuffer() { void TextureArrayGLTest::compressedSubImage1DQueryBuffer() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
@ -1085,6 +1174,35 @@ void TextureArrayGLTest::image2DBuffer() {
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void TextureArrayGLTest::image2DQueryView() {
setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_array>())
CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported."));
Texture2DArray texture;
texture.setImage(0, TextureFormat::RGBA8, ImageView3D{
PixelStorage2DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i(2),
PixelStorage2DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage2DData[testCaseInstanceId()].offset + 2*2*2*4};
MutableImageView3D image{PixelStorage2DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{2}, data};
texture.image(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i(2));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage2DData[testCaseInstanceId()].offset),
PixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
#endif
constexpr UnsignedByte Zero2D[4*4*4*4]{}; constexpr UnsignedByte Zero2D[4*4*4*4]{};
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -1202,6 +1320,33 @@ void TextureArrayGLTest::subImage2DQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureArrayGLTest::subImage2DQueryView() {
setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_array>())
CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
Texture2DArray texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4})
.setSubImage(0, {}, ImageView3D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{4}, SubData2DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage2DData[testCaseInstanceId()].offset + 2*2*2*4};
MutableImageView3D image{PixelStorage2DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{2}, data};
texture.subImage(0, Range3Di::fromSize(Vector3i{1}, Vector3i{2}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i{2});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage2DData[testCaseInstanceId()].offset),
PixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void TextureArrayGLTest::subImage2DQueryBuffer() { void TextureArrayGLTest::subImage2DQueryBuffer() {
setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name);
@ -1316,6 +1461,39 @@ void TextureArrayGLTest::compressedImage2DBuffer() {
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void TextureArrayGLTest::compressedImage2DQueryView() {
setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_array>())
CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
Texture2DArray texture;
texture.setCompressedImage(0, CompressedImageView3D{
CompressedPixelStorage2DData[testCaseInstanceId()].storage,
CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 2},
CompressedPixelStorage2DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorage2DData[testCaseInstanceId()].offset + 2*16};
MutableCompressedImageView3D image{CompressedPixelStorage2DData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 2}, data};
texture.compressedImage(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 2}));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorage2DData[testCaseInstanceId()].offset),
CompressedPixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
#endif
/* Just 12x4x4 zeros compressed using RGBA DXT3 by the driver */ /* Just 12x4x4 zeros compressed using RGBA DXT3 by the driver */
constexpr UnsignedByte CompressedZero2D[3*4*16]{}; constexpr UnsignedByte CompressedZero2D[3*4*16]{};
@ -1480,6 +1658,39 @@ void TextureArrayGLTest::compressedSubImage2DQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureArrayGLTest::compressedSubImage2DQueryView() {
setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_array>())
CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
Texture2DArray texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4, 4})
.setCompressedSubImage(0, {}, CompressedImageView3D{CompressedPixelFormat::RGBAS3tcDxt3,
{12, 4, 4}, CompressedSubData2DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorage2DData[testCaseInstanceId()].offset + 2*16};
MutableCompressedImageView3D image{CompressedPixelStorage2DData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 2}, data};
texture.compressedSubImage(0, Range3Di::fromSize({4, 0, 1}, {4, 4, 2}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 2}));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorage2DData[testCaseInstanceId()].offset),
CompressedPixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void TextureArrayGLTest::compressedSubImage2DQueryBuffer() { void TextureArrayGLTest::compressedSubImage2DQueryBuffer() {
setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name);

338
src/Magnum/GL/Test/TextureGLTest.cpp

@ -140,43 +140,59 @@ struct TextureGLTest: OpenGLTester {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void image1D(); void image1D();
void image1DBuffer(); void image1DBuffer();
void image1DQueryView();
void subImage1D(); void subImage1D();
void subImage1DBuffer(); void subImage1DBuffer();
void subImage1DQuery(); void subImage1DQuery();
void subImage1DQueryView();
void subImage1DQueryBuffer(); void subImage1DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
void compressedImage1D(); void compressedImage1D();
void compressedImage1DBuffer(); void compressedImage1DBuffer();
void compressedImage1DQueryView();
void compressedSubImage1D(); void compressedSubImage1D();
void compressedSubImage1DBuffer(); void compressedSubImage1DBuffer();
void compressedSubImage1DQuery(); void compressedSubImage1DQuery();
void compressedSubImage1DQueryView();
void compressedSubImage1DQueryBuffer(); void compressedSubImage1DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
void image2D(); void image2D();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void image2DBuffer(); void image2DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void image2DQueryView();
#endif
void subImage2D(); void subImage2D();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void subImage2DBuffer(); void subImage2DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void subImage2DQuery(); void subImage2DQuery();
void subImage2DQueryView();
void subImage2DQueryBuffer(); void subImage2DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
void compressedImage2D(); void compressedImage2D();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void compressedImage2DBuffer(); void compressedImage2DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void compressedImage2DQueryView();
#endif
void compressedSubImage2D(); void compressedSubImage2D();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void compressedSubImage2DBuffer(); void compressedSubImage2DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void compressedSubImage2DQuery(); void compressedSubImage2DQuery();
void compressedSubImage2DQueryView();
void compressedSubImage2DQueryBuffer(); void compressedSubImage2DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
@ -184,26 +200,36 @@ struct TextureGLTest: OpenGLTester {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void image3DBuffer(); void image3DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void image3DQueryView();
#endif
void subImage3D(); void subImage3D();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void subImage3DBuffer(); void subImage3DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void subImage3DQuery(); void subImage3DQuery();
void subImage3DQueryView();
void subImage3DQueryBuffer(); void subImage3DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
void compressedImage3D(); void compressedImage3D();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void compressedImage3DBuffer(); void compressedImage3DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void compressedImage3DQueryView();
#endif
void compressedSubImage3D(); void compressedSubImage3D();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void compressedSubImage3DBuffer(); void compressedSubImage3DBuffer();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void compressedSubImage3DQuery(); void compressedSubImage3DQuery();
void compressedSubImage3DQueryView();
void compressedSubImage3DQueryBuffer(); void compressedSubImage3DQueryBuffer();
/* View query assertions tested in AbstractTextureGLTest */
#endif #endif
#endif #endif
@ -501,17 +527,21 @@ TextureGLTest::TextureGLTest() {
addInstancedTests({ addInstancedTests({
&TextureGLTest::image1D, &TextureGLTest::image1D,
&TextureGLTest::image1DBuffer, &TextureGLTest::image1DBuffer,
&TextureGLTest::image1DQueryView,
&TextureGLTest::subImage1D, &TextureGLTest::subImage1D,
&TextureGLTest::subImage1DBuffer, &TextureGLTest::subImage1DBuffer,
&TextureGLTest::subImage1DQuery, &TextureGLTest::subImage1DQuery,
&TextureGLTest::subImage1DQueryView,
&TextureGLTest::subImage1DQueryBuffer}, &TextureGLTest::subImage1DQueryBuffer},
Containers::arraySize(PixelStorage1DData)); Containers::arraySize(PixelStorage1DData));
addTests({&TextureGLTest::compressedImage1D, addTests({&TextureGLTest::compressedImage1D,
&TextureGLTest::compressedImage1DBuffer, &TextureGLTest::compressedImage1DBuffer,
&TextureGLTest::compressedImage1DQueryView,
&TextureGLTest::compressedSubImage1D, &TextureGLTest::compressedSubImage1D,
&TextureGLTest::compressedSubImage1DBuffer, &TextureGLTest::compressedSubImage1DBuffer,
&TextureGLTest::compressedSubImage1DQuery, &TextureGLTest::compressedSubImage1DQuery,
&TextureGLTest::compressedSubImage1DQueryView,
&TextureGLTest::compressedSubImage1DQueryBuffer}); &TextureGLTest::compressedSubImage1DQueryBuffer});
#endif #endif
@ -520,12 +550,16 @@ TextureGLTest::TextureGLTest() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::image2DBuffer, &TextureGLTest::image2DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::image2DQueryView,
#endif
&TextureGLTest::subImage2D, &TextureGLTest::subImage2D,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::subImage2DBuffer, &TextureGLTest::subImage2DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureGLTest::subImage2DQuery, &TextureGLTest::subImage2DQuery,
&TextureGLTest::subImage2DQueryView,
&TextureGLTest::subImage2DQueryBuffer, &TextureGLTest::subImage2DQueryBuffer,
#endif #endif
}, Containers::arraySize(PixelStorage2DData)); }, Containers::arraySize(PixelStorage2DData));
@ -535,12 +569,16 @@ TextureGLTest::TextureGLTest() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::compressedImage2DBuffer, &TextureGLTest::compressedImage2DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::compressedImage2DQueryView,
#endif
&TextureGLTest::compressedSubImage2D, &TextureGLTest::compressedSubImage2D,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::compressedSubImage2DBuffer, &TextureGLTest::compressedSubImage2DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureGLTest::compressedSubImage2DQuery, &TextureGLTest::compressedSubImage2DQuery,
&TextureGLTest::compressedSubImage2DQueryView,
&TextureGLTest::compressedSubImage2DQueryBuffer &TextureGLTest::compressedSubImage2DQueryBuffer
#endif #endif
}, Containers::arraySize(CompressedPixelStorage2DData)); }, Containers::arraySize(CompressedPixelStorage2DData));
@ -551,12 +589,16 @@ TextureGLTest::TextureGLTest() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::image3DBuffer, &TextureGLTest::image3DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::image3DQueryView,
#endif
&TextureGLTest::subImage3D, &TextureGLTest::subImage3D,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::subImage3DBuffer, &TextureGLTest::subImage3DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureGLTest::subImage3DQuery, &TextureGLTest::subImage3DQuery,
&TextureGLTest::subImage3DQueryView,
&TextureGLTest::subImage3DQueryBuffer, &TextureGLTest::subImage3DQueryBuffer,
#endif #endif
}, Containers::arraySize(PixelStorage3DData)); }, Containers::arraySize(PixelStorage3DData));
@ -566,12 +608,16 @@ TextureGLTest::TextureGLTest() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::compressedImage3DBuffer, &TextureGLTest::compressedImage3DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::compressedImage3DQueryView,
#endif
&TextureGLTest::compressedSubImage3D, &TextureGLTest::compressedSubImage3D,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::compressedSubImage3DBuffer, &TextureGLTest::compressedSubImage3DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureGLTest::compressedSubImage3DQuery, &TextureGLTest::compressedSubImage3DQuery,
&TextureGLTest::compressedSubImage3DQueryView,
&TextureGLTest::compressedSubImage3DQueryBuffer &TextureGLTest::compressedSubImage3DQueryBuffer
#endif #endif
}, Containers::arraySize(CompressedPixelStorage3DData)); }, Containers::arraySize(CompressedPixelStorage3DData));
@ -1319,6 +1365,30 @@ void TextureGLTest::image1DBuffer() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureGLTest::image1DQueryView() {
setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name);
Texture1D texture;
texture.setImage(0, TextureFormat::RGBA8, ImageView1D{
PixelStorage1DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, 2,
PixelStorage1DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage1DData[testCaseInstanceId()].offset + 2*4};
MutableImageView1D image{PixelStorage1DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, 2, data};
texture.image(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), 2);
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage1DData[testCaseInstanceId()].offset),
PixelStorage1DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
constexpr UnsignedByte Zero1D[4*4] = {}; constexpr UnsignedByte Zero1D[4*4] = {};
constexpr UnsignedByte SubData1DComplete[]{ constexpr UnsignedByte SubData1DComplete[]{
0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0 0, 0, 0, 0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0
@ -1395,6 +1465,31 @@ void TextureGLTest::subImage1DQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureGLTest::subImage1DQueryView() {
setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
Texture1D texture;
texture.setStorage(1, TextureFormat::RGBA8, 4)
.setSubImage(0, {}, ImageView1D{PixelFormat::RGBA, PixelType::UnsignedByte, 4, SubData1DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage1DData[testCaseInstanceId()].offset + 2*4};
MutableImageView1D image{PixelStorage1DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, 2, data};
texture.subImage(0, Range1Di::fromSize(1, 2), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), 2);
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage1DData[testCaseInstanceId()].offset),
PixelStorage1DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void TextureGLTest::subImage1DQueryBuffer() { void TextureGLTest::subImage1DQueryBuffer() {
setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name);
@ -1428,6 +1523,10 @@ void TextureGLTest::compressedImage1DBuffer() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
void TextureGLTest::compressedImage1DQueryView() {
CORRADE_SKIP("No 1D texture compression format exists.");
}
void TextureGLTest::compressedSubImage1D() { void TextureGLTest::compressedSubImage1D() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
@ -1440,6 +1539,10 @@ void TextureGLTest::compressedSubImage1DQuery() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
void TextureGLTest::compressedSubImage1DQueryView() {
CORRADE_SKIP("No 1D texture compression format exists.");
}
void TextureGLTest::compressedSubImage1DQueryBuffer() { void TextureGLTest::compressedSubImage1DQueryBuffer() {
CORRADE_SKIP("No 1D texture compression format exists."); CORRADE_SKIP("No 1D texture compression format exists.");
} }
@ -1516,6 +1619,32 @@ void TextureGLTest::image2DBuffer() {
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void TextureGLTest::image2DQueryView() {
setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name);
Texture2D texture;
texture.setImage(0, TextureFormat::RGBA8, ImageView2D{
PixelStorage2DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i(2),
PixelStorage2DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage2DData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView2D image{PixelStorage2DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, data};
texture.image(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i(2));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage2DData[testCaseInstanceId()].offset),
PixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
#endif
constexpr UnsignedByte Zero2D[4*4*4]{}; constexpr UnsignedByte Zero2D[4*4*4]{};
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -1620,6 +1749,31 @@ void TextureGLTest::subImage2DQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureGLTest::subImage2DQueryView() {
setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4})
.setSubImage(0, {}, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{4}, SubData2DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage2DData[testCaseInstanceId()].offset + 2*2*4};
MutableImageView2D image{PixelStorage2DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, data};
texture.subImage(0, Range2Di::fromSize(Vector2i{1}, Vector2i{2}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i{2});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage2DData[testCaseInstanceId()].offset),
PixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void TextureGLTest::subImage2DQueryBuffer() { void TextureGLTest::subImage2DQueryBuffer() {
setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name);
@ -1727,6 +1881,38 @@ void TextureGLTest::compressedImage2DBuffer() {
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void TextureGLTest::compressedImage2DQueryView() {
setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
Texture2D texture;
texture.setCompressedImage(0, CompressedImageView2D{
CompressedPixelStorage2DData[testCaseInstanceId()].storage,
CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4},
CompressedPixelStorage2DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorage2DData[testCaseInstanceId()].offset + 1*16};
MutableCompressedImageView2D image{CompressedPixelStorage2DData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, data};
texture.compressedImage(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i{4});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorage2DData[testCaseInstanceId()].offset),
CompressedPixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
#endif
/* Just 12x4 zeros compressed using RGBA DXT3 by the driver */ /* Just 12x4 zeros compressed using RGBA DXT3 by the driver */
constexpr UnsignedByte CompressedZero2D[3*16]{}; constexpr UnsignedByte CompressedZero2D[3*16]{};
@ -1856,6 +2042,36 @@ void TextureGLTest::compressedSubImage2DQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureGLTest::compressedSubImage2DQueryView() {
setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_compression_s3tc>())
CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported."));
if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
Texture2D texture;
texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4})
.setCompressedSubImage(0, {}, CompressedImageView2D{CompressedPixelFormat::RGBAS3tcDxt3, {12, 4}, CompressedSubData2DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorage2DData[testCaseInstanceId()].offset + 1*16};
MutableCompressedImageView2D image{CompressedPixelStorage2DData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBAS3tcDxt3, Vector2i{4}, data};
texture.compressedSubImage(0, Range2Di::fromSize({4, 0}, Vector2i{4}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector2i{4});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorage2DData[testCaseInstanceId()].offset),
CompressedPixelStorage2DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void TextureGLTest::compressedSubImage2DQueryBuffer() { void TextureGLTest::compressedSubImage2DQueryBuffer() {
setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name);
@ -1950,6 +2166,32 @@ void TextureGLTest::image3DBuffer() {
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void TextureGLTest::image3DQueryView() {
setTestCaseDescription(PixelStorage3DData[testCaseInstanceId()].name);
Texture3D texture;
texture.setImage(0, TextureFormat::RGBA8, ImageView3D{
PixelStorage3DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i(2),
PixelStorage3DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage3DData[testCaseInstanceId()].offset + 2*2*2*4};
MutableImageView3D image{PixelStorage3DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{2}, data};
texture.image(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i(2));
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage3DData[testCaseInstanceId()].offset),
PixelStorage3DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
#endif
constexpr UnsignedByte Zero3D[4*4*4*4]{}; constexpr UnsignedByte Zero3D[4*4*4*4]{};
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -2063,6 +2305,31 @@ void TextureGLTest::subImage3DQuery() {
TestSuite::Compare::Container); TestSuite::Compare::Container);
} }
void TextureGLTest::subImage3DQueryView() {
setTestCaseDescription(PixelStorage3DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
Texture3D texture;
texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4})
.setSubImage(0, {}, ImageView3D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{4}, SubData3DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{PixelStorage3DData[testCaseInstanceId()].offset + 2*2*2*4};
MutableImageView3D image{PixelStorage3DData[testCaseInstanceId()].storage,
PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{2}, data};
texture.subImage(0, Range3Di::fromSize(Vector3i{1}, Vector3i{2}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i{2});
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(PixelStorage3DData[testCaseInstanceId()].offset),
PixelStorage3DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
void TextureGLTest::subImage3DQueryBuffer() { void TextureGLTest::subImage3DQueryBuffer() {
setTestCaseDescription(PixelStorage3DData[testCaseInstanceId()].name); setTestCaseDescription(PixelStorage3DData[testCaseInstanceId()].name);
@ -2163,6 +2430,40 @@ void TextureGLTest::compressedImage3DBuffer() {
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
void TextureGLTest::compressedImage3DQueryView() {
setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_compression_bptc>())
CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported."));
if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
Texture3D texture;
texture.setCompressedImage(0, CompressedImageView3D{
CompressedPixelStorage3DData[testCaseInstanceId()].storage,
CompressedPixelFormat::RGBABptcUnorm, Vector3i{4},
CompressedPixelStorage3DData[testCaseInstanceId()].dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorage2DData[testCaseInstanceId()].offset + 64};
MutableCompressedImageView3D image{CompressedPixelStorage2DData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBABptcUnorm, Vector3i{4}, data};
texture.compressedImage(0, image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), Vector3i{4});
{
CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{},
"Mesa drivers can't handle non-default compressed 3D pixel storage.");
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorage3DData[testCaseInstanceId()].offset),
CompressedPixelStorage3DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
}
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/* Just 12x4x4 zeros compressed using RGBA BPTC Unorm by the driver */ /* Just 12x4x4 zeros compressed using RGBA BPTC Unorm by the driver */
constexpr UnsignedByte CompressedZero3D[3*4*16]{ constexpr UnsignedByte CompressedZero3D[3*4*16]{
@ -2325,6 +2626,43 @@ void TextureGLTest::compressedSubImage3DQuery() {
} }
} }
void TextureGLTest::compressedSubImage3DQueryView() {
setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name);
if(!Context::current().isExtensionSupported<Extensions::ARB::get_texture_sub_image>())
CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported."));
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_compression_bptc>())
CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported."));
if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::compressed_texture_pixel_storage>())
CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported."));
if(CompressedPixelStorage3DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported<Extensions::ARB::internalformat_query2>())
CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported."));
Texture3D texture;
texture.setStorage(1, TextureFormat::CompressedRGBABptcUnorm, {12, 4, 4})
.setCompressedSubImage(0, {}, CompressedImageView3D{CompressedPixelFormat::RGBABptcUnorm, {12, 4, 4}, CompressedSubData3DComplete});
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> data{CompressedPixelStorage2DData[testCaseInstanceId()].offset + 64};
MutableCompressedImageView3D image{CompressedPixelStorage2DData[testCaseInstanceId()].storage, CompressedPixelFormat::RGBABptcUnorm, Vector3i{4}, data};
texture.compressedSubImage(0, Range3Di::fromSize({4, 0, 0}, Vector3i{4}), image);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(image.size(), (Vector3i{4}));
{
CORRADE_EXPECT_FAIL_IF(CompressedPixelStorage3DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && (Context::current().detectedDriver() & Context::DetectedDriver::NVidia),
"Default compressed pixel storage behaves weirdly with BPTC compression on NVidia.");
CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa),
"Mesa drivers can't handle compressed 3D pixel storage for subimages.");
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()).suffix(CompressedPixelStorage3DData[testCaseInstanceId()].offset),
CompressedPixelStorage3DData[testCaseInstanceId()].data,
TestSuite::Compare::Container);
}
}
void TextureGLTest::compressedSubImage3DQueryBuffer() { void TextureGLTest::compressedSubImage3DQueryBuffer() {
setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name); setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name);

70
src/Magnum/GL/Texture.h

@ -754,8 +754,10 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* *
* Image parameters like format and type of pixel data are taken from * Image parameters like format and type of pixel data are taken from
* given image, image size is taken from the texture using * given image, image size is taken from the texture using
* @ref imageSize(). The storage is not reallocated if it is large * @ref imageSize(). The storage is not reallocated if it is large
* enough to contain the new data. * enough to contain the new data --- however if you want to read into
* existing memory or *ensure* a reallocation does not happen, use
* @ref image(Int, BasicMutableImageView<dimensions>&) instead.
* *
* If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is * If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is
* not available, the texture is bound before the operation (if not * not available, the texture is bound before the operation (if not
@ -785,6 +787,17 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
*/ */
Image<dimensions> image(Int level, Image<dimensions>&& image); Image<dimensions> image(Int level, Image<dimensions>&& image);
/**
* @brief Read given texture mip level to an image view
*
* Compared to @ref image(Int, Image<dimensions>&) the function reads
* the pixels into the memory provided by @p image, expecting it's not
* @cpp nullptr @ce and its size is the same as size of given @p level.
*/
void image(Int level, BasicMutableImageView<dimensions>& image) {
AbstractTexture::image<dimensions>(level, image);
}
/** /**
* @brief Read given texture mip level to a buffer image * @brief Read given texture mip level to a buffer image
* @param level Mip level * @param level Mip level
@ -819,7 +832,10 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* *
* Compression format and data size are taken from the texture, image * Compression format and data size are taken from the texture, image
* size is taken using @ref imageSize(). The storage is not reallocated * size is taken using @ref imageSize(). The storage is not reallocated
* if it is large enough to contain the new data. * if it is large enough to contain the new data --- however if you
* want to read into existing memory or *ensure* a reallocation does
* not happen, use @ref compressedImage(Int, BasicMutableCompressedImageView<dimensions>&)
* instead.
* *
* If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is * If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is
* not available, the texture is bound before the operation (if not * not available, the texture is bound before the operation (if not
@ -853,6 +869,18 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
*/ */
CompressedImage<dimensions> compressedImage(Int level, CompressedImage<dimensions>&& image); CompressedImage<dimensions> compressedImage(Int level, CompressedImage<dimensions>&& image);
/**
* @brief Read given compressed texture mip level to an image view
*
* Compared to @ref compressedImage(Int, CompressedImage<dimensions>&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as size of given @p level.
*/
void compressedImage(Int level, BasicMutableCompressedImageView<dimensions>& image) {
AbstractTexture::compressedImage<dimensions>(level, image);
}
/** /**
* @brief Read given compressed texture mip level to a buffer image * @brief Read given compressed texture mip level to a buffer image
* @param level Mip level * @param level Mip level
@ -890,7 +918,10 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* *
* Image parameters like format and type of pixel data are taken from * Image parameters like format and type of pixel data are taken from
* given image. The storage is not reallocated if it is large enough to * given image. The storage is not reallocated if it is large enough to
* contain the new data. * contain the new data --- however if you want to read into existing
* memory or *ensure* a reallocation does not happen, use
* @ref subImage(Int, const RangeTypeFor<dimensions, Int>&, BasicMutableImageView<dimensions>&)
* instead.
* *
* The operation is protected from buffer overflow. * The operation is protected from buffer overflow.
* @see @fn_gl_keyword{GetTextureSubImage} * @see @fn_gl_keyword{GetTextureSubImage}
@ -910,6 +941,18 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
*/ */
Image<dimensions> subImage(Int level, const RangeTypeFor<dimensions, Int>& range, Image<dimensions>&& image); Image<dimensions> subImage(Int level, const RangeTypeFor<dimensions, Int>& range, Image<dimensions>&& image);
/**
* @brief Read a range of given texture mip level to an image view
*
* Compared to @ref subImage(Int, const RangeTypeFor<dimensions, Int>&, Image<dimensions>&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce and its size is the same as
* @p range size.
*/
void subImage(Int level, const RangeTypeFor<dimensions, Int>& range, BasicMutableImageView<dimensions>& image) {
AbstractTexture::subImage<dimensions>(level, range, image);
}
/** /**
* @brief Read a range of given texture mip level to a buffer image * @brief Read a range of given texture mip level to a buffer image
* @param level Mip level * @param level Mip level
@ -943,7 +986,12 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* @param range Range to read * @param range Range to read
* @param image Image where to put the compressed data * @param image Image where to put the compressed data
* *
* Compression format and data size are taken from the texture. * Compression format and data size are taken from the texture. The
* storage is not reallocated if it is large enough to contain the new
* data --- however if you want to read into existing memory or
* *ensure* a reallocation does not happen, use
* @ref compressedSubImage(Int, const RangeTypeFor<dimensions, Int>&, BasicMutableCompressedImageView<dimensions>&)
* instead.
* @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter}, * @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter},
* eventually @fn_gl{GetTexLevelParameter} with * eventually @fn_gl{GetTexLevelParameter} with
* @def_gl{TEXTURE_INTERNAL_FORMAT}, then possibly * @def_gl{TEXTURE_INTERNAL_FORMAT}, then possibly
@ -974,6 +1022,18 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
*/ */
CompressedImage<dimensions> compressedSubImage(Int level, const RangeTypeFor<dimensions, Int>& range, CompressedImage<dimensions>&& image); CompressedImage<dimensions> compressedSubImage(Int level, const RangeTypeFor<dimensions, Int>& range, CompressedImage<dimensions>&& image);
/**
* @brief Read a range of given compressed texture mip level to an image view
*
* Compared to @ref compressedSubImage(Int, const RangeTypeFor<dimensions, Int>&, CompressedImage<dimensions>&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as @p range size.
*/
void compressedSubImage(Int level, const RangeTypeFor<dimensions, Int>& range, BasicMutableCompressedImageView<dimensions>& image) {
AbstractTexture::compressedSubImage<dimensions>(level, range, image);
}
/** /**
* @brief Read a range of given compressed texture mip level to a buffer image * @brief Read a range of given compressed texture mip level to a buffer image
* @param level Mip level * @param level Mip level

47
src/Magnum/GL/TextureArray.h

@ -522,6 +522,17 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
*/ */
Image<dimensions+1> image(Int level, Image<dimensions+1>&& image); Image<dimensions+1> image(Int level, Image<dimensions+1>&& image);
/**
* @brief Read given texture mip level to an image view
*
* Compared to @ref image(Int, Image<dimensions+1>&) the function reads
* the pixels into the memory provided by @p image, expecting it's not
* @cpp nullptr @ce and its size is the same as size of given @p level.
*/
void image(Int level, BasicMutableImageView<dimensions+1>& image) {
AbstractTexture::image<dimensions+1>(level, image);
}
/** /**
* @brief Read given texture mip level to a buffer image * @brief Read given texture mip level to a buffer image
* *
@ -566,6 +577,18 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
*/ */
CompressedImage<dimensions+1> compressedImage(Int level, CompressedImage<dimensions+1>&& image); CompressedImage<dimensions+1> compressedImage(Int level, CompressedImage<dimensions+1>&& image);
/**
* @brief Read given compressed texture mip level to an image view
*
* Compared to @ref compressedImage(Int, CompressedImage<dimensions+1>&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as size of given @p level.
*/
void compressedImage(Int level, BasicMutableCompressedImageView<dimensions+1>& image) {
AbstractTexture::compressedImage<dimensions+1>(level, image);
}
/** /**
* @brief Read given compressed texture mip level to a buffer image * @brief Read given compressed texture mip level to a buffer image
* *
@ -611,6 +634,18 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
*/ */
Image<dimensions+1> subImage(Int level, const RangeTypeFor<dimensions+1, Int>& range, Image<dimensions+1>&& image); Image<dimensions+1> subImage(Int level, const RangeTypeFor<dimensions+1, Int>& range, Image<dimensions+1>&& image);
/**
* @brief Read a range of given texture mip level to an image view
*
* Compared to @ref subImage(Int, const RangeTypeFor<dimensions+1, Int>&, Image<dimensions+1>&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce and its size is the same as
* @p range size.
*/
void subImage(Int level, const RangeTypeFor<dimensions+1, Int>& range, BasicMutableImageView<dimensions+1>& image) {
AbstractTexture::subImage<dimensions+1>(level, range, image);
}
/** /**
* @brief Read a range of given texture mip level to a buffer image * @brief Read a range of given texture mip level to a buffer image
* *
@ -661,6 +696,18 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
*/ */
CompressedImage<dimensions+1> compressedSubImage(Int level, const RangeTypeFor<dimensions+1, Int>& range, CompressedImage<dimensions+1>&& image); CompressedImage<dimensions+1> compressedSubImage(Int level, const RangeTypeFor<dimensions+1, Int>& range, CompressedImage<dimensions+1>&& image);
/**
* @brief Read a range of given compressed texture mip level to an image view
*
* Compared to @ref compressedSubImage(Int, const RangeTypeFor<dimensions+1, Int>&, CompressedImage<dimensions+1>&)
* the function reads the pixels into the memory provided by @p image,
* expecting it's not @cpp nullptr @ce, its format is the same as
* texture format and its size is the same as @p range size.
*/
void compressedSubImage(Int level, const RangeTypeFor<dimensions+1, Int>& range, BasicMutableCompressedImageView<dimensions+1>& image) {
AbstractTexture::compressedSubImage<dimensions+1>(level, range, image);
}
/** /**
* @brief Read a range of given compressed texture mip level to a buffer image * @brief Read a range of given compressed texture mip level to a buffer image
* *

Loading…
Cancel
Save