Browse Source

Text: add a test case for using *GlyphCacheArrayGL with just one layer.

It works everywhere except on Chrome WebGL 2, which complains that pixel
unpack parameters are incorrect. Which is a very helpful error on its
own, fortunately I know already where the problem is.
pull/680/head
Vladimír Vondruš 10 months ago
parent
commit
27b29c50a7
  1. 128
      src/Magnum/Text/Test/DistanceFieldGlyphCacheGLTest.cpp
  2. 72
      src/Magnum/Text/Test/GlyphCacheGLTest.cpp

128
src/Magnum/Text/Test/DistanceFieldGlyphCacheGLTest.cpp

@ -77,6 +77,7 @@ struct DistanceFieldGlyphCacheGLTest: GL::OpenGLTester {
void setImage(); void setImage();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void setImageArraySingleLayer();
void setImageArray(); void setImageArray();
#endif #endif
void setImageEdgeClamp(); void setImageEdgeClamp();
@ -86,6 +87,7 @@ struct DistanceFieldGlyphCacheGLTest: GL::OpenGLTester {
void setProcessedImage(); void setProcessedImage();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void setProcessedImageArraySingleLayer();
void setProcessedImageArray(); void setProcessedImageArray();
#endif #endif
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
@ -218,6 +220,9 @@ DistanceFieldGlyphCacheGLTest::DistanceFieldGlyphCacheGLTest() {
Containers::arraySize(SetImageData)); Containers::arraySize(SetImageData));
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&DistanceFieldGlyphCacheGLTest::setImageArraySingleLayer},
Containers::arraySize(SetImageData));
addInstancedTests({&DistanceFieldGlyphCacheGLTest::setImageArray}, addInstancedTests({&DistanceFieldGlyphCacheGLTest::setImageArray},
Containers::arraySize(SetImageArrayData)); Containers::arraySize(SetImageArrayData));
#endif #endif
@ -236,7 +241,8 @@ DistanceFieldGlyphCacheGLTest::DistanceFieldGlyphCacheGLTest() {
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addTests({&DistanceFieldGlyphCacheGLTest::setProcessedImageArray}); addTests({&DistanceFieldGlyphCacheGLTest::setProcessedImageArraySingleLayer,
&DistanceFieldGlyphCacheGLTest::setProcessedImageArray});
#endif #endif
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
@ -493,6 +499,76 @@ void DistanceFieldGlyphCacheGLTest::setImage() {
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest::setImageArraySingleLayer() {
auto&& data = SetImageData[testCaseInstanceId()];
setTestCaseDescription(data.name);
/* Like setImage(), but using a DistanceFieldGlyphCacheArrayGL with a
single layer to verify that there isn't any corner case where a regular
2D cache would work but array not. With GlyphCacheArrayGL, Chrome WebGL
2 *requires* image height to be set in the pixel storage for non-zero
skip even if uploading to the very first slice. In this particular case
not because the internal processing input texture is just 2D, not 2D
array, but including the test just in case. */
Containers::Pointer<Trade::AbstractImporter> importer;
if(!(importer = _manager.loadAndInstantiate("TgaImporter")))
CORRADE_SKIP("TgaImporter plugin not found.");
CORRADE_VERIFY(importer->openFile(Utility::Path::join(TEXTURETOOLS_DISTANCEFIELDGLTEST_DIR, "input.tga")));
CORRADE_COMPARE(importer->image2DCount(), 1);
Containers::Optional<Trade::ImageData2D> inputImage = importer->image2D(0);
CORRADE_VERIFY(inputImage);
CORRADE_COMPARE(inputImage->format(), PixelFormat::R8Unorm);
CORRADE_COMPARE(inputImage->size(), (Vector2i{256, 256}));
DistanceFieldGlyphCacheArrayGL cache{{data.sourceSize, 1}, data.size, 32};
/* Clear the target texture to avoid random garbage getting in when the
data.flushRange isn't covering the whole output */
Containers::Array<char> zeros{ValueInit, data.size.product()*pixelFormatSize(cache.processedFormat())};
cache.texture().setSubImage(0, {},
/* On ES2, R8Unorm maps to Luminance, but here it's actually Red if
EXT_texture_rg is supported */
#if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
cache.processedFormat() == PixelFormat::R8Unorm ?
ImageView2D{GL::PixelFormat::Red, GL::PixelType::UnsignedByte, data.size, zeros} :
#endif
ImageView2D{cache.processedFormat(), data.size, zeros}
);
Containers::StridedArrayView2D<const UnsignedByte> src = inputImage->pixels<UnsignedByte>();
/* Test also uploading under an offset */
Utility::copy(src, cache.image().pixels<UnsignedByte>()[0].sliceSize({
std::size_t(data.sourceOffset.y()),
std::size_t(data.sourceOffset.x())}, src.size()));
cache.flushImage(data.flushRange);
MAGNUM_VERIFY_NO_GL_ERROR();
/* On GLES processedImage() isn't implemented as it'd mean creating a
temporary framebuffer. Do it via DebugTools here instead, we cannot
really verify that the size matches, but at least something. */
#ifndef MAGNUM_TARGET_GLES
Image3D actual3 = cache.processedImage();
/** @todo ugh have slicing on images directly already */
MutableImageView2D actual{actual3.format(), actual3.size().xy(), actual3.data()};
#else
Image2D actual = DebugTools::textureSubImage(cache.texture(), 0, 0, {{}, data.size}, cache.processedFormat());
#endif
MAGNUM_VERIFY_NO_GL_ERROR();
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
/* The format may be three-component, consider just the first channel */
Containers::StridedArrayView3D<const char> pixels = actual.pixels();
CORRADE_COMPARE_WITH((Containers::arrayCast<2, const UnsignedByte>(pixels.prefix({pixels.size()[0], pixels.size()[1], 1})).exceptPrefix(data.offset)),
Utility::Path::join(TEXTURETOOLS_DISTANCEFIELDGLTEST_DIR, "output.tga"),
/* Same threshold as in TextureTools DistanceFieldGLTest */
(DebugTools::CompareImageToFile{_manager, 1.0f, 0.178f}));
}
void DistanceFieldGlyphCacheGLTest::setImageArray() { void DistanceFieldGlyphCacheGLTest::setImageArray() {
auto&& data = SetImageArrayData[testCaseInstanceId()]; auto&& data = SetImageArrayData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
@ -766,6 +842,56 @@ void DistanceFieldGlyphCacheGLTest::setProcessedImage() {
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest::setProcessedImageArraySingleLayer() {
/* Like setProcessedImage(), but using a DistanceFieldGlyphCacheArrayGL
with a single layer to verify that there isn't any corner case where a
regular 2D cache would work but array not. With GlyphCacheArrayGL,
Chrome WebGL 2 *requires* image height to be set in the pixel storage
for non-zero skip even if uploading to the very first slice. In this
particular case not because the image passed to setProcessedImage() is
under user's control, but including the test just in case.
Unlike setProcessedImage() the test is not instanced because the
instanced data are there just for deprecated APIs that aren't present in
the array variant. */
DistanceFieldGlyphCacheArrayGL cache({64, 32, 1}, {16, 8}, 16);
/* Clear the texture first, as it'd have random garbage otherwise */
UnsignedByte zeros[16*8]{};
cache.setProcessedImage({}, ImageView2D{PixelFormat::R8Unorm, {16, 8}, zeros});
MAGNUM_VERIFY_NO_GL_ERROR();
cache.setProcessedImage({8, 4}, ImageView2D{PixelFormat::R8Unorm, {8, 4}, InputData});
MAGNUM_VERIFY_NO_GL_ERROR();
/* On GLES processedImage() isn't implemented as it'd mean creating a
temporary framebuffer. Do it via DebugTools here instead, we cannot
really verify that the size matches, but at least something. */
#ifndef MAGNUM_TARGET_GLES
Image3D actual3 = cache.processedImage();
/** @todo ugh have slicing on images directly already */
MutableImageView2D actual{actual3.format(), actual3.size().xy(), actual3.data()};
#else
Image2D actual = DebugTools::textureSubImage(cache.texture(), 0, 0, {{}, {16, 8}}, cache.processedFormat());
#endif
MAGNUM_VERIFY_NO_GL_ERROR();
UnsignedByte expected[]{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0xff, 0x11, 0xee, 0x22, 0xdd, 0x33, 0xcc,
0, 0, 0, 0, 0, 0, 0, 0, 0x44, 0xbb, 0x55, 0xaa, 0x66, 0x99, 0x77, 0x88,
};
CORRADE_COMPARE_AS(actual,
(ImageView2D{PixelFormat::R8Unorm, {16, 8}, expected}),
DebugTools::CompareImage);
}
void DistanceFieldGlyphCacheGLTest::setProcessedImageArray() { void DistanceFieldGlyphCacheGLTest::setProcessedImageArray() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>())

72
src/Magnum/Text/Test/GlyphCacheGLTest.cpp

@ -90,6 +90,7 @@ struct GlyphCacheGLTest: GL::OpenGLTester {
void setImage(); void setImage();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void setImageArraySingleLayer();
void setImageArray(); void setImageArray();
#endif #endif
void setImageFourChannel(); void setImageFourChannel();
@ -137,6 +138,7 @@ GlyphCacheGLTest::GlyphCacheGLTest() {
&GlyphCacheGLTest::setImage, &GlyphCacheGLTest::setImage,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&GlyphCacheGLTest::setImageArraySingleLayer,
&GlyphCacheGLTest::setImageArray, &GlyphCacheGLTest::setImageArray,
#endif #endif
&GlyphCacheGLTest::setImageFourChannel, &GlyphCacheGLTest::setImageFourChannel,
@ -508,6 +510,76 @@ void GlyphCacheGLTest::setImage() {
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void GlyphCacheGLTest::setImageArraySingleLayer() {
/* Like setImage(), but using a GlyphCacheArrayGL with a single layer to
verify that there isn't any corner case where a regular 2D cache would
work but array not.
In particular, Chrome WebGL 2 *requires* image height to be set in the
pixel storage for non-zero skip even if uploading to the very first
slice. Firefox doesn't. */
GlyphCacheArrayGL cache{PixelFormat::R8Unorm, {16, 8, 1}};
/* Fill the texture with non-zero data to verify the padding gets uploaded
as well */
cache.texture().setSubImage(0, {}, Image3D{PixelFormat::R8Unorm, {16, 8, 1}, Containers::Array<char>{DirectInit, 16*8, '\xcd'}});
Utility::copy(
Containers::StridedArrayView2D<const UnsignedByte>{InputData, {4, 8}},
cache.image().pixels<UnsignedByte>()[0].sliceSize({4, 8}, {4, 8}));
cache.flushImage(Range2Di::fromSize({8, 4}, {8, 4}));
MAGNUM_VERIFY_NO_GL_ERROR();
ImageView3D actual = cache.image();
MAGNUM_VERIFY_NO_GL_ERROR();
/* The CPU-side image is zero-initialized, what was set above in the
texture isn't present there */
/** @todo ugh have slicing on images directly already, and 3D image
comparison */
CORRADE_COMPARE_AS((ImageView2D{actual.format(), actual.size().xy(), actual.data()}),
(ImageView2D{PixelFormat::R8Unorm, {16, 8}, ExpectedData}),
DebugTools::CompareImage);
/* The actual texture has just the slice updated, the rest stays. On GLES
we cannot really verify that the size matches, but at least
something. */
#ifndef MAGNUM_TARGET_GLES
Image3D image = cache.texture().image(0, {PixelFormat::R8Unorm});
#else
Image2D image = DebugTools::textureSubImage(cache.texture(), 0, 0, {{}, {16, 8}}, {PixelFormat::R8Unorm});
#endif
const UnsignedByte expectedTextureData[]{
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0,
0x00, 0xff, 0x11, 0xee, 0x22, 0xdd, 0x33, 0xcc,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0,
0x44, 0xbb, 0x55, 0xaa, 0x66, 0x99, 0x77, 0x88
};
#ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE_AS(image.pixels<UnsignedByte>()[0],
(ImageView2D{PixelFormat::R8Unorm, {16, 8}, expectedTextureData}),
DebugTools::CompareImage);
#else
CORRADE_COMPARE_AS(image.pixels<UnsignedByte>(),
(ImageView2D{PixelFormat::R8Unorm, {16, 8}, expectedTextureData}),
DebugTools::CompareImage);
#endif
}
void GlyphCacheGLTest::setImageArray() { void GlyphCacheGLTest::setImageArray() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>())

Loading…
Cancel
Save