@ -44,6 +44,9 @@
# include "Magnum/GL/Extensions.h"
# include "Magnum/GL/Extensions.h"
# include "Magnum/GL/PixelFormat.h"
# include "Magnum/GL/PixelFormat.h"
# include "Magnum/GL/Texture.h"
# include "Magnum/GL/Texture.h"
# ifndef MAGNUM_TARGET_GLES2
# include "Magnum/GL/TextureArray.h"
# endif
# include "Magnum/Text/DistanceFieldGlyphCacheGL.h"
# include "Magnum/Text/DistanceFieldGlyphCacheGL.h"
# include "Magnum/Trade/AbstractImporter.h"
# include "Magnum/Trade/AbstractImporter.h"
# include "Magnum/Trade/ImageData.h"
# include "Magnum/Trade/ImageData.h"
@ -56,15 +59,35 @@ struct DistanceFieldGlyphCacheGLTest: GL::OpenGLTester {
explicit DistanceFieldGlyphCacheGLTest ( ) ;
explicit DistanceFieldGlyphCacheGLTest ( ) ;
void construct ( ) ;
void construct ( ) ;
# ifndef MAGNUM_TARGET_GLES2
void constructArray ( ) ;
# endif
void constructSizeRatioNotMultipleOfTwo ( ) ;
void constructSizeRatioNotMultipleOfTwo ( ) ;
# ifndef MAGNUM_TARGET_GLES2
void constructSizeRatioNotMultipleOfTwoArray ( ) ;
# endif
void constructCopy ( ) ;
void constructCopy ( ) ;
# ifndef MAGNUM_TARGET_GLES2
void constructCopyArray ( ) ;
# endif
void constructMove ( ) ;
void constructMove ( ) ;
# ifndef MAGNUM_TARGET_GLES2
void constructMoveArray ( ) ;
# endif
void setImage ( ) ;
void setImage ( ) ;
# ifndef MAGNUM_TARGET_GLES2
void setImageArray ( ) ;
# endif
void setImageEdgeClamp ( ) ;
void setImageEdgeClamp ( ) ;
# ifndef MAGNUM_TARGET_GLES2
void setImageEdgeClampArray ( ) ;
# endif
void setProcessedImage ( ) ;
void setProcessedImage ( ) ;
# ifndef MAGNUM_TARGET_GLES2
void setProcessedImageArray ( ) ;
# endif
# ifdef MAGNUM_BUILD_DEPRECATED
# ifdef MAGNUM_BUILD_DEPRECATED
void setDistanceFieldImageUnsupportedGLFormat ( ) ;
void setDistanceFieldImageUnsupportedGLFormat ( ) ;
# endif
# endif
@ -103,6 +126,61 @@ const struct {
{ } } ,
{ } } ,
} ;
} ;
/* Expands upon SetImageData with third dimension. For simplicity only a single
layer always contains data to process , but it ' s changed which one it is to
verify all uploaded layers get processed . */
const struct {
const char * name ;
Vector3i sourceSize ;
Vector2i size ;
Vector3i sourceOffset ;
Range3Di flushRange ;
Containers : : Size2D offset ;
} SetImageArrayData [ ] {
{ " single layer " ,
{ 256 , 256 , 1 } , { 64 , 64 } , { } ,
{ { } , { 256 , 256 , 1 } } ,
{ } } ,
{ " multiple layers, data in the first layer " ,
{ 256 , 256 , 7 } , { 64 , 64 } , { } ,
{ { } , { 256 , 256 , 7 } } ,
{ } } ,
{ " multiple layers, data in the middle layer " ,
{ 256 , 256 , 7 } , { 64 , 64 } , { 0 , 0 , 3 } ,
{ { } , { 256 , 256 , 7 } } ,
{ } } ,
{ " multiple layers, data in the last layer " ,
{ 256 , 256 , 7 } , { 64 , 64 } , { 0 , 0 , 6 } ,
{ { } , { 256 , 256 , 7 } } ,
{ } } ,
{ " single layer, upload with offset " ,
{ 512 , 384 , 1 } , { 128 , 96 } , { 256 , 128 , 0 } ,
{ { 256 , 128 , 0 } , { 512 , 384 , 1 } } ,
{ 128 / 4 , 256 / 4 } } ,
{ " multiple layers, upload with offset, data in the first flushed layer " ,
{ 512 , 384 , 7 } , { 128 , 96 } , { 256 , 128 , 3 } ,
{ { 256 , 128 , 3 } , { 512 , 384 , 7 } } ,
{ 128 / 4 , 256 / 4 } } ,
{ " multiple layers, upload with offset, data in the middle flushed layer " ,
{ 512 , 384 , 7 } , { 128 , 96 } , { 256 , 128 , 3 } ,
{ { 256 , 128 , 1 } , { 512 , 384 , 5 } } ,
{ 128 / 4 , 256 / 4 } } ,
{ " multiple layers, upload with offset, data in the last flushed layer " ,
{ 512 , 384 , 7 } , { 128 , 96 } , { 256 , 128 , 4 } ,
{ { 256 , 128 , 1 } , { 512 , 384 , 5 } } ,
{ 128 / 4 , 256 / 4 } } ,
/* These two don't have the other layer offset variants as that should be
sufficiently tested above */
{ " tight flush rectangle " ,
{ 256 , 256 , 7 } , { 64 , 64 } , { 0 , 0 , 3 } ,
{ { 48 , 48 , 2 } , { 208 , 208 , 6 } } ,
{ } } ,
{ " tight flush rectangle, ratio not a multiple of 2 " ,
{ 256 , 256 , 7 } , { 64 , 64 } , { 0 , 0 , 3 } ,
{ { 47 , 48 , 2 } , { 208 , 209 , 6 } } ,
{ } } ,
} ;
# ifdef MAGNUM_BUILD_DEPRECATED
# ifdef MAGNUM_BUILD_DEPRECATED
const struct {
const struct {
const char * name ;
const char * name ;
@ -117,22 +195,49 @@ const struct {
DistanceFieldGlyphCacheGLTest : : DistanceFieldGlyphCacheGLTest ( ) {
DistanceFieldGlyphCacheGLTest : : DistanceFieldGlyphCacheGLTest ( ) {
addTests ( { & DistanceFieldGlyphCacheGLTest : : construct ,
addTests ( { & DistanceFieldGlyphCacheGLTest : : construct ,
# ifndef MAGNUM_TARGET_GLES2
& DistanceFieldGlyphCacheGLTest : : constructArray ,
# endif
& DistanceFieldGlyphCacheGLTest : : constructSizeRatioNotMultipleOfTwo ,
& DistanceFieldGlyphCacheGLTest : : constructSizeRatioNotMultipleOfTwo ,
# ifndef MAGNUM_TARGET_GLES2
& DistanceFieldGlyphCacheGLTest : : constructSizeRatioNotMultipleOfTwoArray ,
# endif
& DistanceFieldGlyphCacheGLTest : : constructCopy ,
& DistanceFieldGlyphCacheGLTest : : constructCopy ,
& DistanceFieldGlyphCacheGLTest : : constructMove } ) ;
# ifndef MAGNUM_TARGET_GLES2
& DistanceFieldGlyphCacheGLTest : : constructCopyArray ,
# endif
& DistanceFieldGlyphCacheGLTest : : constructMove ,
# ifndef MAGNUM_TARGET_GLES2
& DistanceFieldGlyphCacheGLTest : : constructMoveArray
# endif
} ) ;
addInstancedTests ( { & DistanceFieldGlyphCacheGLTest : : setImage } ,
addInstancedTests ( { & DistanceFieldGlyphCacheGLTest : : setImage } ,
Containers : : arraySize ( SetImageData ) ) ;
Containers : : arraySize ( SetImageData ) ) ;
addTests ( { & DistanceFieldGlyphCacheGLTest : : setImageEdgeClamp } ) ;
# ifndef MAGNUM_TARGET_GLES2
addInstancedTests ( { & DistanceFieldGlyphCacheGLTest : : setImageArray } ,
Containers : : arraySize ( SetImageArrayData ) ) ;
# endif
addTests ( { & DistanceFieldGlyphCacheGLTest : : setImageEdgeClamp ,
# ifndef MAGNUM_TARGET_GLES2
& DistanceFieldGlyphCacheGLTest : : setImageEdgeClampArray
# endif
} ) ;
# ifndef MAGNUM_BUILD_DEPRECATED
# ifndef MAGNUM_BUILD_DEPRECATED
addTests ( { & DistanceFieldGlyphCacheGLTest : : setProcessedImage } ) ;
addTests ( { & DistanceFieldGlyphCacheGLTest : : setProcessedImage } ) ;
# else
# else
addInstancedTests ( { & DistanceFieldGlyphCacheGLTest : : setProcessedImage } ,
addInstancedTests ( { & DistanceFieldGlyphCacheGLTest : : setProcessedImage } ,
Containers : : arraySize ( SetProcessedImageData ) ) ;
Containers : : arraySize ( SetProcessedImageData ) ) ;
# endif
# ifndef MAGNUM_TARGET_GLES2
addTests ( { & DistanceFieldGlyphCacheGLTest : : setProcessedImageArray } ) ;
# endif
# ifdef MAGNUM_BUILD_DEPRECATED
addTests ( { & DistanceFieldGlyphCacheGLTest : : setDistanceFieldImageUnsupportedGLFormat } ) ;
addTests ( { & DistanceFieldGlyphCacheGLTest : : setDistanceFieldImageUnsupportedGLFormat } ) ;
# endif
# endif
@ -181,6 +286,32 @@ void DistanceFieldGlyphCacheGLTest::construct() {
# endif
# endif
}
}
# ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest : : constructArray ( ) {
# ifndef MAGNUM_TARGET_GLES
if ( ! GL : : Context : : current ( ) . isExtensionSupported < GL : : Extensions : : EXT : : texture_array > ( ) )
CORRADE_SKIP ( GL : : Extensions : : EXT : : texture_array : : string ( ) < < " is not supported. " ) ;
# endif
DistanceFieldGlyphCacheArrayGL cache { { 256 , 512 , 7 } , { 64 , 128 } , 16 } ;
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
# ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE ( cache . features ( ) , GlyphCacheFeature : : ImageProcessing | GlyphCacheFeature : : ProcessedImageDownload ) ;
# else
CORRADE_COMPARE ( cache . features ( ) , GlyphCacheFeature : : ImageProcessing ) ;
# endif
/* The input format is always single-channel */
CORRADE_COMPARE ( cache . format ( ) , PixelFormat : : R8Unorm ) ;
CORRADE_COMPARE ( cache . size ( ) , ( Vector3i { 256 , 512 , 7 } ) ) ;
CORRADE_COMPARE ( cache . processedFormat ( ) , PixelFormat : : R8Unorm ) ;
CORRADE_COMPARE ( cache . processedSize ( ) , ( Vector3i { 64 , 128 , 7 } ) ) ;
# ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE ( cache . texture ( ) . imageSize ( 0 ) , ( Vector3i { 64 , 128 , 7 } ) ) ;
# endif
}
# endif
void DistanceFieldGlyphCacheGLTest : : constructSizeRatioNotMultipleOfTwo ( ) {
void DistanceFieldGlyphCacheGLTest : : constructSizeRatioNotMultipleOfTwo ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
@ -206,11 +337,50 @@ void DistanceFieldGlyphCacheGLTest::constructSizeRatioNotMultipleOfTwo() {
TestSuite : : Compare : : String ) ;
TestSuite : : Compare : : String ) ;
}
}
# ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest : : constructSizeRatioNotMultipleOfTwoArray ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
# ifndef MAGNUM_TARGET_GLES
if ( ! GL : : Context : : current ( ) . isExtensionSupported < GL : : Extensions : : EXT : : texture_array > ( ) )
CORRADE_SKIP ( GL : : Extensions : : EXT : : texture_array : : string ( ) < < " is not supported. " ) ;
# endif
/* This should be fine. THe depth doesn't affect anything. */
DistanceFieldGlyphCacheArrayGL { { Vector2i { 23 * 14 } , 7 } , Vector2i { 23 } , 4 } ;
/* It's the same assert as in TextureTools::DistanceFieldGL */
Containers : : String out ;
Error redirectError { & out } ;
DistanceFieldGlyphCacheArrayGL { { Vector2i { 23 * 14 } , 7 } , Vector2i { 23 * 2 } , 4 } ;
/* Verify also just one axis wrong */
DistanceFieldGlyphCacheArrayGL { { Vector2i { 23 * 14 } , 7 } , { 23 * 2 , 23 } , 4 } ;
DistanceFieldGlyphCacheArrayGL { { Vector2i { 23 * 14 } , 7 } , { 23 , 23 * 2 } , 4 } ;
/* Almost correct except that it's not an integer multiply */
DistanceFieldGlyphCacheArrayGL { { Vector2i { 23 * 14 } , 7 } , { 22 , 23 } , 4 } ;
DistanceFieldGlyphCacheArrayGL { { Vector2i { 23 * 14 } , 7 } , { 23 , 22 } , 4 } ;
CORRADE_COMPARE_AS ( out ,
" Text::DistanceFieldGlyphCacheArrayGL: expected source and processed size ratio to be a multiple of 2, got {322, 322} and {46, 46} \n "
" Text::DistanceFieldGlyphCacheArrayGL: expected source and processed size ratio to be a multiple of 2, got {322, 322} and {46, 23} \n "
" Text::DistanceFieldGlyphCacheArrayGL: expected source and processed size ratio to be a multiple of 2, got {322, 322} and {23, 46} \n "
" Text::DistanceFieldGlyphCacheArrayGL: expected source and processed size ratio to be a multiple of 2, got {322, 322} and {22, 23} \n "
" Text::DistanceFieldGlyphCacheArrayGL: expected source and processed size ratio to be a multiple of 2, got {322, 322} and {23, 22} \n " ,
TestSuite : : Compare : : String ) ;
}
# endif
void DistanceFieldGlyphCacheGLTest : : constructCopy ( ) {
void DistanceFieldGlyphCacheGLTest : : constructCopy ( ) {
CORRADE_VERIFY ( ! std : : is_copy_constructible < DistanceFieldGlyphCacheGL > { } ) ;
CORRADE_VERIFY ( ! std : : is_copy_constructible < DistanceFieldGlyphCacheGL > { } ) ;
CORRADE_VERIFY ( ! std : : is_copy_assignable < DistanceFieldGlyphCacheGL > { } ) ;
CORRADE_VERIFY ( ! std : : is_copy_assignable < DistanceFieldGlyphCacheGL > { } ) ;
}
}
# ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest : : constructCopyArray ( ) {
CORRADE_VERIFY ( ! std : : is_copy_constructible < DistanceFieldGlyphCacheArrayGL > { } ) ;
CORRADE_VERIFY ( ! std : : is_copy_assignable < DistanceFieldGlyphCacheArrayGL > { } ) ;
}
# endif
void DistanceFieldGlyphCacheGLTest : : constructMove ( ) {
void DistanceFieldGlyphCacheGLTest : : constructMove ( ) {
DistanceFieldGlyphCacheGL a { { 256 , 512 } , { 64 , 64 } , 3 } ;
DistanceFieldGlyphCacheGL a { { 256 , 512 } , { 64 , 64 } , 3 } ;
@ -225,6 +395,27 @@ void DistanceFieldGlyphCacheGLTest::constructMove() {
CORRADE_VERIFY ( std : : is_nothrow_move_assignable < DistanceFieldGlyphCacheGL > : : value ) ;
CORRADE_VERIFY ( std : : is_nothrow_move_assignable < DistanceFieldGlyphCacheGL > : : value ) ;
}
}
# ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest : : constructMoveArray ( ) {
# ifndef MAGNUM_TARGET_GLES
if ( ! GL : : Context : : current ( ) . isExtensionSupported < GL : : Extensions : : EXT : : texture_array > ( ) )
CORRADE_SKIP ( GL : : Extensions : : EXT : : texture_array : : string ( ) < < " is not supported. " ) ;
# endif
DistanceFieldGlyphCacheArrayGL a { { 256 , 512 , 7 } , { 64 , 64 } , 3 } ;
DistanceFieldGlyphCacheArrayGL b = Utility : : move ( a ) ;
CORRADE_COMPARE ( b . size ( ) , ( Vector3i { 256 , 512 , 7 } ) ) ;
DistanceFieldGlyphCacheArrayGL c { { 2 , 4 , 3 } , { 1 , 2 } , 1 } ;
c = Utility : : move ( b ) ;
CORRADE_COMPARE ( c . size ( ) , ( Vector3i { 256 , 512 , 7 } ) ) ;
CORRADE_VERIFY ( std : : is_nothrow_move_constructible < DistanceFieldGlyphCacheGL > : : value ) ;
CORRADE_VERIFY ( std : : is_nothrow_move_assignable < DistanceFieldGlyphCacheGL > : : value ) ;
}
# endif
void DistanceFieldGlyphCacheGLTest : : setImage ( ) {
void DistanceFieldGlyphCacheGLTest : : setImage ( ) {
auto & & data = SetImageData [ testCaseInstanceId ( ) ] ;
auto & & data = SetImageData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
setTestCaseDescription ( data . name ) ;
@ -297,6 +488,70 @@ void DistanceFieldGlyphCacheGLTest::setImage() {
( DebugTools : : CompareImageToFile { _manager , 1.0f , 0.178f } ) ) ;
( DebugTools : : CompareImageToFile { _manager , 1.0f , 0.178f } ) ) ;
}
}
# ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest : : setImageArray ( ) {
auto & & data = SetImageArrayData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
# ifndef MAGNUM_TARGET_GLES
if ( ! GL : : Context : : current ( ) . isExtensionSupported < GL : : Extensions : : EXT : : texture_array > ( ) )
CORRADE_SKIP ( GL : : Extensions : : EXT : : texture_array : : string ( ) < < " is not supported. " ) ;
# endif
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 , 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 ( ) * data . sourceSize . z ( ) * pixelFormatSize ( cache . processedFormat ( ) ) } ;
cache . texture ( ) . setSubImage ( 0 , { } , ImageView3D { cache . processedFormat ( ) , { data . size , data . sourceSize . z ( ) } , zeros } ) ;
Containers : : StridedArrayView3D < const UnsignedByte > src = inputImage - > pixels < UnsignedByte > ( ) ;
/* Test also uploading under an offset */
Utility : : copy ( src , cache . image ( ) . pixels < UnsignedByte > ( ) . sliceSize ( {
std : : size_t ( data . sourceOffset . z ( ) ) ,
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 .
Only one layer always contains the processed data , get just that one . */
# 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 ( ) . exceptPrefix ( actual3 . size ( ) . xy ( ) . product ( ) * actual3 . pixelSize ( ) * data . sourceOffset . z ( ) ) } ;
# else
Image2D actual = DebugTools : : textureSubImage ( cache . texture ( ) , 0 , data . sourceOffset . z ( ) , { { } , 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 } ) ) ;
}
# endif
void DistanceFieldGlyphCacheGLTest : : setImageEdgeClamp ( ) {
void DistanceFieldGlyphCacheGLTest : : setImageEdgeClamp ( ) {
/* Verifies that the input texture filtering clamp is set to edge to not
/* Verifies that the input texture filtering clamp is set to edge to not
have content from one side leak to another when the data don ' t have
have content from one side leak to another when the data don ' t have
@ -352,6 +607,63 @@ void DistanceFieldGlyphCacheGLTest::setImageEdgeClamp() {
CORRADE_COMPARE ( dst [ 1 ] [ 0 ] , ' \x00 ' ) ;
CORRADE_COMPARE ( dst [ 1 ] [ 0 ] , ' \x00 ' ) ;
}
}
# ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest : : setImageEdgeClampArray ( ) {
# ifndef MAGNUM_TARGET_GLES
if ( ! GL : : Context : : current ( ) . isExtensionSupported < GL : : Extensions : : EXT : : texture_array > ( ) )
CORRADE_SKIP ( GL : : Extensions : : EXT : : texture_array : : string ( ) < < " is not supported. " ) ;
# endif
/* Like setImageEdgeClamp(), but for texture arrays. As texelFetch() is
always used in this case , a leak should never happen , nevertheless it ' s
good to have it verified . */
DistanceFieldGlyphCacheArrayGL cache { { 8 , 4 , 1 } , { 4 , 2 } , 4 } ;
/* Make the right edge all white */
Containers : : StridedArrayView2D < UnsignedByte > src = cache . image ( ) . pixels < UnsignedByte > ( ) [ 0 ] ;
src [ 0 ] [ 7 ] = ' \xff ' ;
src [ 1 ] [ 7 ] = ' \xff ' ;
src [ 2 ] [ 7 ] = ' \xff ' ;
src [ 3 ] [ 7 ] = ' \xff ' ;
cache . flushImage ( { { } , { 8 , 4 } } ) ;
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 , { { } , { 4 , 2 } } , cache . processedFormat ( ) ) ;
# endif
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
/* The format may be three-component, consider just the first channel */
Containers : : StridedArrayView3D < const char > dst3 = actual . pixels ( ) ;
Containers : : StridedArrayView2D < const UnsignedByte > dst = Containers : : arrayCast < 2 , const UnsignedByte > ( dst3 . prefix ( { dst3 . size ( ) [ 0 ] , dst3 . size ( ) [ 1 ] , 1 } ) ) ;
/* On the right side the pixels should be non-zero to verify processing got
done at all */
CORRADE_VERIFY ( dst [ 0 ] [ 3 ] > 0 ) ;
CORRADE_VERIFY ( dst [ 1 ] [ 3 ] > 0 ) ;
/* On the left side the pixels should be completely zero, without the right
side leaking for example due to accidental repeat clamp */
CORRADE_COMPARE ( dst [ 0 ] [ 0 ] , ' \x00 ' ) ;
CORRADE_COMPARE ( dst [ 1 ] [ 0 ] , ' \x00 ' ) ;
}
# endif
const UnsignedByte InputData [ ] {
0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 ,
0x88 , 0x99 , 0xaa , 0xbb , 0xcc , 0xdd , 0xee , 0xff ,
0x00 , 0xff , 0x11 , 0xee , 0x22 , 0xdd , 0x33 , 0xcc ,
0x44 , 0xbb , 0x55 , 0xaa , 0x66 , 0x99 , 0x77 , 0x88 ,
} ;
void DistanceFieldGlyphCacheGLTest : : setProcessedImage ( ) {
void DistanceFieldGlyphCacheGLTest : : setProcessedImage ( ) {
# ifdef MAGNUM_BUILD_DEPRECATED
# ifdef MAGNUM_BUILD_DEPRECATED
auto & & data = SetProcessedImageData [ testCaseInstanceId ( ) ] ;
auto & & data = SetProcessedImageData [ testCaseInstanceId ( ) ] ;
@ -371,13 +683,6 @@ void DistanceFieldGlyphCacheGLTest::setProcessedImage() {
cache . setProcessedImage ( { } , ImageView2D { PixelFormat : : R8Unorm , { 16 , 8 } , zeros } ) ;
cache . setProcessedImage ( { } , ImageView2D { PixelFormat : : R8Unorm , { 16 , 8 } , zeros } ) ;
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
UnsignedByte imageData [ ] {
0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 ,
0x88 , 0x99 , 0xaa , 0xbb , 0xcc , 0xdd , 0xee , 0xff ,
0x00 , 0xff , 0x11 , 0xee , 0x22 , 0xdd , 0x33 , 0xcc ,
0x44 , 0xbb , 0x55 , 0xaa , 0x66 , 0x99 , 0x77 , 0x88 ,
} ;
# ifdef MAGNUM_BUILD_DEPRECATED
# ifdef MAGNUM_BUILD_DEPRECATED
if ( data . deprecated ) {
if ( data . deprecated ) {
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_IGNORE_DEPRECATED_PUSH
@ -388,14 +693,14 @@ void DistanceFieldGlyphCacheGLTest::setProcessedImage() {
# else
# else
GL : : PixelFormat : : Luminance ,
GL : : PixelFormat : : Luminance ,
# endif
# endif
GL : : PixelType : : UnsignedByte , { 8 , 4 } , image Data} ) ;
GL : : PixelType : : UnsignedByte , { 8 , 4 } , Input Data} ) ;
else
else
cache . setDistanceFieldImage ( { 8 , 4 } , ImageView2D { PixelFormat : : R8Unorm , { 8 , 4 } , image Data} ) ;
cache . setDistanceFieldImage ( { 8 , 4 } , ImageView2D { PixelFormat : : R8Unorm , { 8 , 4 } , Input Data} ) ;
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_IGNORE_DEPRECATED_POP
} else
} else
# endif
# endif
{
{
cache . setProcessedImage ( { 8 , 4 } , ImageView2D { PixelFormat : : R8Unorm , { 8 , 4 } , image Data} ) ;
cache . setProcessedImage ( { 8 , 4 } , ImageView2D { PixelFormat : : R8Unorm , { 8 , 4 } , Input Data} ) ;
}
}
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
@ -438,6 +743,93 @@ void DistanceFieldGlyphCacheGLTest::setProcessedImage() {
DebugTools : : CompareImage ) ;
DebugTools : : CompareImage ) ;
}
}
# ifndef MAGNUM_TARGET_GLES2
void DistanceFieldGlyphCacheGLTest : : setProcessedImageArray ( ) {
# ifndef MAGNUM_TARGET_GLES
if ( ! GL : : Context : : current ( ) . isExtensionSupported < GL : : Extensions : : EXT : : texture_array > ( ) )
CORRADE_SKIP ( GL : : Extensions : : EXT : : texture_array : : string ( ) < < " is not supported. " ) ;
# endif
/* Adapted from GlyphCacheGLTest::setImageArray(), with a difference that a
single - component is used so the X size is 16 instead of 8 */
DistanceFieldGlyphCacheArrayGL cache { { 64 , 32 , 4 } , { 16 , 8 } , 16 } ;
/* Clear the texture first, as it'd have random garbage otherwise */
UnsignedByte zeros [ 16 * 8 * 4 ] { } ;
cache . setProcessedImage ( { } , ImageView3D { PixelFormat : : R8Unorm , { 16 , 8 , 4 } , zeros } ) ;
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
cache . setProcessedImage ( { 6 , 4 , 1 } , ImageView3D { PixelFormat : : R8Unorm , { 8 , 2 , 2 } , 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 image = cache . processedImage ( ) ;
/** @todo ugh have slicing on images directly already, and 3D image
comparison */
const std : : size_t sliceSize = image . size ( ) . xy ( ) . product ( ) ;
ImageView2D image0 { image . format ( ) , image . size ( ) . xy ( ) , image . data ( ) } ;
ImageView2D image1 { image . format ( ) , image . size ( ) . xy ( ) , image . data ( ) . exceptPrefix ( 1 * sliceSize ) } ;
ImageView2D image2 { image . format ( ) , image . size ( ) . xy ( ) , image . data ( ) . exceptPrefix ( 2 * sliceSize ) } ;
ImageView2D image3 { image . format ( ) , image . size ( ) . xy ( ) , image . data ( ) . exceptPrefix ( 3 * sliceSize ) } ;
# else
Image2D image0 = DebugTools : : textureSubImage ( cache . texture ( ) , 0 , 0 , { { } , { 16 , 8 } } , { PixelFormat : : R8Unorm } ) ;
Image2D image1 = DebugTools : : textureSubImage ( cache . texture ( ) , 0 , 1 , { { } , { 16 , 8 } } , { PixelFormat : : R8Unorm } ) ;
Image2D image2 = DebugTools : : textureSubImage ( cache . texture ( ) , 0 , 2 , { { } , { 16 , 8 } } , { PixelFormat : : R8Unorm } ) ;
Image2D image3 = DebugTools : : textureSubImage ( cache . texture ( ) , 0 , 3 , { { } , { 16 , 8 } } , { PixelFormat : : R8Unorm } ) ;
# endif
MAGNUM_VERIFY_NO_GL_ERROR ( ) ;
const UnsignedByte expected03 [ 16 * 8 ] { } ;
const UnsignedByte expected1 [ ] {
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 , 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 ,
} ;
const UnsignedByte expected2 [ ] {
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 , 0xff , 0x11 , 0xee , 0x22 , 0xdd , 0x33 , 0xcc , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0x44 , 0xbb , 0x55 , 0xaa , 0x66 , 0x99 , 0x77 , 0x88 , 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 ,
} ;
CORRADE_COMPARE_AS ( image0 ,
( ImageView2D { PixelFormat : : R8Unorm , { 16 , 8 } , expected03 } ) ,
DebugTools : : CompareImage ) ;
{
# ifdef MAGNUM_TARGET_GLES
CORRADE_EXPECT_FAIL_IF ( GL : : Context : : current ( ) . detectedDriver ( ) > = GL : : Context : : DetectedDriver : : SwiftShader ,
" SwiftShader is trash and doesn't implement reading from non-zero array layers. " ) ;
# endif
CORRADE_COMPARE_AS ( image1 ,
( ImageView2D { PixelFormat : : R8Unorm , { 16 , 8 } , expected1 } ) ,
DebugTools : : CompareImage ) ;
CORRADE_COMPARE_AS ( image2 ,
( ImageView2D { PixelFormat : : R8Unorm , { 16 , 8 } , expected2 } ) ,
DebugTools : : CompareImage ) ;
}
/* This is broken on SwiftShader too, returning the first layer (or all
zeros ) but since we expect the same as first layer ( which is all zeros ) ,
it passes */
CORRADE_COMPARE_AS ( image3 ,
( ImageView2D { PixelFormat : : R8Unorm , { 16 , 8 } , expected03 } ) ,
DebugTools : : CompareImage ) ;
}
# endif
# ifdef MAGNUM_BUILD_DEPRECATED
# ifdef MAGNUM_BUILD_DEPRECATED
void DistanceFieldGlyphCacheGLTest : : setDistanceFieldImageUnsupportedGLFormat ( ) {
void DistanceFieldGlyphCacheGLTest : : setDistanceFieldImageUnsupportedGLFormat ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
CORRADE_SKIP_IF_NO_ASSERT ( ) ;