Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Typedefs | Functions | Variables
impeller::testing Namespace Reference

Classes

struct  BlendModeSelection
 
struct  CheckSameSignature
 
struct  CheckSameSignature< Ret(Args...), Ret(Args...)>
 
struct  ColorBlendTestData
 
class  CommandBufferMock
 
class  CompareFunctionUIData
 
class  ContextMock
 
class  ContextSpy
 
struct  CVTest
 
struct  Foo
 
class  GaussianBlurFilterContentsTest
 
class  GoldenDigest
 Manages a global variable for tracking instances of golden images. More...
 
class  GoldenTests
 
struct  MaskBlurTestConfig
 
class  MetalScreenshot
 A screenshot that was produced from MetalScreenshotter. More...
 
class  MetalScreenshotter
 
class  MockAllocator
 
class  MockBlitPass
 
class  MockCapabilities
 
class  MockCommandBuffer
 
class  MockCommandQueue
 
class  MockDeviceBuffer
 
class  MockFence
 
class  MockGLES
 Provides a mocked version of the |ProcTableGLES| class. More...
 
class  MockImpellerContext
 
class  MockRenderPass
 
class  MockSampler
 
class  MockSamplerLibrary
 
class  MockTexture
 
class  MockVulkanContextBuilder
 
class  NoopCommandQueue
 
class  RendererDartTest
 
struct  RWFoo
 
class  Screenshot
 
class  Screenshotter
 
class  TestAllocator
 
class  TestPassDelegate
 
struct  TextRenderOptions
 
class  VulkanScreenshotter
 
class  WorkingDirectory
 

Typedefs

using AiksTest = AiksPlayground
 
using AiksCanvasTest = ::testing::Test
 
using DisplayListTest = DlPlayground
 
using EntityTest = EntityPlayground
 
using HostBufferTest = EntityPlayground
 
using EntityPassTargetTest = EntityPlayground
 
using RenderTargetCacheTest = EntityPlayground
 
using DriverInfoVKTest = PlaygroundTest
 
using RendererTest = PlaygroundTest
 
using BlitPassTest = PlaygroundTest
 
using ComputeSubgroupTest = ComputePlaygroundTest
 
using ComputeTest = ComputePlaygroundTest
 
using DeviceBufferTest = Playground
 
using RuntimeStageTest = RuntimeStagePlayground
 
using TypographerTest = PlaygroundTest
 

Functions

 TEST_P (AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
 
 TEST_P (AiksTest, BlendModeShouldCoverWholeScreen)
 
 TEST_P (AiksTest, CanDrawPaintWithAdvancedBlend)
 
 TEST_P (AiksTest, DrawPaintWithAdvancedBlendOverFilter)
 
 TEST_P (AiksTest, DrawAdvancedBlendPartlyOffscreen)
 
 TEST_P (AiksTest, PaintBlendModeIsRespected)
 
 TEST_P (AiksTest, BlendModePlusAlphaWideGamut)
 
 TEST_P (AiksTest, BlendModePlusAlphaColorFilterWideGamut)
 
static BlendModeSelection GetBlendModeSelection ()
 
 TEST_P (AiksTest, ColorWheel)
 
 TEST_P (AiksTest, ForegroundBlendSubpassCollapseOptimization)
 
 TEST_P (AiksTest, ClearBlend)
 
static Picture BlendModeTest (Vector2 content_scale, BlendMode blend_mode, const std::shared_ptr< Image > &src_image, const std::shared_ptr< Image > &dst_image, Scalar src_alpha)
 
 TEST_P (AiksTest, CanDrawPaintMultipleTimesInteractive)
 
 TEST_P (AiksTest, ForegroundPipelineBlendAppliesTransformCorrectly)
 
 TEST_P (AiksTest, ForegroundAdvancedBlendAppliesTransformCorrectly)
 
 TEST_P (AiksTest, CanRenderMaskBlurHugeSigma)
 
 TEST_P (AiksTest, CanRenderForegroundBlendWithMaskBlur)
 
 TEST_P (AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur)
 
 TEST_P (AiksTest, CanRenderBackdropBlurInteractive)
 
 TEST_P (AiksTest, CanRenderBackdropBlur)
 
 TEST_P (AiksTest, CanRenderBackdropBlurHugeSigma)
 
 TEST_P (AiksTest, CanRenderClippedBlur)
 
 TEST_P (AiksTest, ClippedBlurFilterRendersCorrectlyInteractive)
 
 TEST_P (AiksTest, ClippedBlurFilterRendersCorrectly)
 
 TEST_P (AiksTest, ClearBlendWithBlur)
 
 TEST_P (AiksTest, BlurHasNoEdge)
 
 TEST_P (AiksTest, BlurredRectangleWithShader)
 
 TEST_P (AiksTest, MaskBlurWithZeroSigmaIsSkipped)
 
static Picture MaskBlurVariantTest (const AiksTest &test_context, const MaskBlurTestConfig &config)
 
 TEST_P (AiksTest, GaussianBlurAtPeripheryVertical)
 
 TEST_P (AiksTest, GaussianBlurAtPeripheryHorizontal)
 
 TEST_P (AiksTest, GaussianBlurWithoutDecalSupport)
 
 TEST_P (AiksTest, GaussianBlurOneDimension)
 
 TEST_P (AiksTest, GaussianBlurRotatedAndClipped)
 
 TEST_P (AiksTest, GaussianBlurScaledAndClipped)
 
 TEST_P (AiksTest, GaussianBlurRotatedAndClippedInteractive)
 
 TEST_P (AiksTest, GaussianBlurSolidColorTinyMipMap)
 
 TEST_P (AiksTest, GaussianBlurBackdropTinyMipMap)
 
 TEST_P (AiksTest, GaussianBlurAnimatedBackdrop)
 
 TEST_P (AiksTest, GaussianBlurStyleInnerGradient)
 
 TEST_P (AiksTest, GaussianBlurStyleSolidGradient)
 
 TEST_P (AiksTest, GaussianBlurStyleOuterGradient)
 
 TEST_P (AiksTest, GaussianBlurStyleInner)
 
 TEST_P (AiksTest, GaussianBlurStyleOuter)
 
 TEST_P (AiksTest, GaussianBlurStyleSolid)
 
 TEST_P (AiksTest, MaskBlurTexture)
 
 TEST_P (AiksTest, GuassianBlurUpdatesMipmapContents)
 
 TEST_P (AiksTest, GaussianBlurSetsMipCountOnPass)
 
 TEST_P (AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget)
 
 TEST_P (AiksTest, GaussianBlurMipMapNestedLayer)
 
 TEST_P (AiksTest, GaussianBlurMipMapImageFilter)
 
 TEST_P (AiksTest, GaussianBlurMipMapSolidColor)
 
 TEST_P (AiksTest, MaskBlurDoesntStretchContents)
 
 TEST_P (AiksTest, CanRenderLinearGradientClamp)
 
 TEST_P (AiksTest, CanRenderLinearGradientRepeat)
 
 TEST_P (AiksTest, CanRenderLinearGradientMirror)
 
 TEST_P (AiksTest, CanRenderLinearGradientDecal)
 
 TEST_P (AiksTest, CanRenderLinearGradientDecalWithColorFilter)
 
static void CanRenderLinearGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
 
 TEST_P (AiksTest, CanRenderLinearGradientWithDitheringDisabled)
 
 TEST_P (AiksTest, CanRenderLinearGradientWithDitheringEnabled)
 
static void CanRenderRadialGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
 
 TEST_P (AiksTest, CanRenderRadialGradientWithDitheringDisabled)
 
 TEST_P (AiksTest, CanRenderRadialGradientWithDitheringEnabled)
 
static void CanRenderSweepGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
 
 TEST_P (AiksTest, CanRenderSweepGradientWithDitheringDisabled)
 
 TEST_P (AiksTest, CanRenderSweepGradientWithDitheringEnabled)
 
static void CanRenderConicalGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
 
 TEST_P (AiksTest, CanRenderConicalGradientWithDitheringDisabled)
 
 TEST_P (AiksTest, CanRenderConicalGradientWithDitheringEnabled)
 
 TEST_P (AiksTest, CanRenderLinearGradientWithOverlappingStopsClamp)
 
 TEST_P (AiksTest, CanRenderLinearGradientManyColorsClamp)
 
 TEST_P (AiksTest, CanRenderLinearGradientManyColorsRepeat)
 
 TEST_P (AiksTest, CanRenderLinearGradientManyColorsMirror)
 
 TEST_P (AiksTest, CanRenderLinearGradientManyColorsDecal)
 
 TEST_P (AiksTest, CanRenderLinearGradientWayManyColorsClamp)
 
 TEST_P (AiksTest, CanRenderLinearGradientManyColorsUnevenStops)
 
 TEST_P (AiksTest, CanRenderLinearGradientMaskBlur)
 
 TEST_P (AiksTest, CanRenderRadialGradient)
 
 TEST_P (AiksTest, CanRenderRadialGradientManyColors)
 
 TEST_P (AiksTest, CanRenderSweepGradientClamp)
 
 TEST_P (AiksTest, CanRenderSweepGradientRepeat)
 
 TEST_P (AiksTest, CanRenderSweepGradientMirror)
 
 TEST_P (AiksTest, CanRenderSweepGradientDecal)
 
 TEST_P (AiksTest, CanRenderSweepGradientManyColorsClamp)
 
 TEST_P (AiksTest, CanRenderSweepGradientManyColorsRepeat)
 
 TEST_P (AiksTest, CanRenderSweepGradientManyColorsMirror)
 
 TEST_P (AiksTest, CanRenderSweepGradientManyColorsDecal)
 
 TEST_P (AiksTest, CanRenderConicalGradient)
 
 TEST_P (AiksTest, CanRenderGradientDecalWithBackground)
 
 APPLY_COLOR_FILTER_GRADIENT_TEST (Linear)
 
 APPLY_COLOR_FILTER_GRADIENT_TEST (Radial)
 
 APPLY_COLOR_FILTER_GRADIENT_TEST (Conical)
 
 APPLY_COLOR_FILTER_GRADIENT_TEST (Sweep)
 
 TEST_P (AiksTest, GradientStrokesRenderCorrectly)
 
 TEST_P (AiksTest, RotateColorFilteredPath)
 
 TEST_P (AiksTest, CanRenderStrokes)
 
 TEST_P (AiksTest, CanRenderCurvedStrokes)
 
 TEST_P (AiksTest, CanRenderThickCurvedStrokes)
 
 TEST_P (AiksTest, CanRenderStrokePathThatEndsAtSharpTurn)
 
 TEST_P (AiksTest, CanRenderStrokePathWithCubicLine)
 
 TEST_P (AiksTest, CanRenderDifferencePaths)
 
 TEST_P (AiksTest, CanDrawAnOpenPath)
 
 TEST_P (AiksTest, CanDrawAnOpenPathThatIsntARect)
 
 TEST_P (AiksTest, SolidStrokesRenderCorrectly)
 
 TEST_P (AiksTest, DrawLinesRenderCorrectly)
 
 TEST_P (AiksTest, DrawRectStrokesRenderCorrectly)
 
 TEST_P (AiksTest, DrawRectStrokesWithBevelJoinRenderCorrectly)
 
 TEST_P (AiksTest, CanDrawMultiContourConvexPath)
 
 TEST_P (AiksTest, ArcWithZeroSweepAndBlur)
 
 TEST_P (AiksTest, CanRenderClips)
 
 TEST_P (AiksTest, CanRenderOverlappingMultiContourPath)
 
 INSTANTIATE_PLAYGROUND_SUITE (AiksTest)
 
 TEST_P (AiksTest, CanvasCTMCanBeUpdated)
 
 TEST_P (AiksTest, CanvasCanPushPopCTM)
 
 TEST_P (AiksTest, CanRenderColoredRect)
 
 TEST_P (AiksTest, CanRenderImage)
 
 TEST_P (AiksTest, CanRenderInvertedImageWithColorFilter)
 
 TEST_P (AiksTest, CanRenderColorFilterWithInvertColors)
 
 TEST_P (AiksTest, CanRenderColorFilterWithInvertColorsDrawPaint)
 
 TEST_P (AiksTest, CanRenderTiledTextureClamp)
 
 TEST_P (AiksTest, CanRenderTiledTextureRepeat)
 
 TEST_P (AiksTest, CanRenderTiledTextureMirror)
 
 TEST_P (AiksTest, CanRenderTiledTextureDecal)
 
 TEST_P (AiksTest, CanRenderTiledTextureClampWithTranslate)
 
 TEST_P (AiksTest, CanRenderImageRect)
 
 TEST_P (AiksTest, CanRenderSimpleClips)
 
 TEST_P (AiksTest, CanRenderNestedClips)
 
 TEST_P (AiksTest, CanRenderDifferenceClips)
 
 TEST_P (AiksTest, CanRenderWithContiguousClipRestores)
 
 TEST_P (AiksTest, ClipsUseCurrentTransform)
 
 TEST_P (AiksTest, CanSaveLayerStandalone)
 
 TEST_P (AiksTest, CanRenderDifferentShapesWithSameColorSource)
 
 TEST_P (AiksTest, CanPictureConvertToImage)
 
 TEST_P (AiksTest, CanEmptyPictureConvertToImage)
 
 TEST_P (AiksTest, CanRenderGroupOpacity)
 
 TEST_P (AiksTest, CoordinateConversionsAreCorrect)
 
 TEST_P (AiksTest, CanPerformFullScreenMSAA)
 
 TEST_P (AiksTest, CanPerformSkew)
 
 TEST_P (AiksTest, CanPerformSaveLayerWithBounds)
 
 TEST_P (AiksTest, CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated)
 
 TEST_P (AiksTest, CanRenderRoundedRectWithNonUniformRadii)
 
bool RenderTextInCanvasSkia (const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string_view &font_fixture, TextRenderOptions options={})
 
bool RenderTextInCanvasSTB (const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string &font_fixture, TextRenderOptions options={})
 
 TEST_P (AiksTest, CanRenderTextFrame)
 
 TEST_P (AiksTest, CanRenderTextFrameSTB)
 
 TEST_P (AiksTest, TextFrameSubpixelAlignment)
 
 TEST_P (AiksTest, CanRenderItalicizedText)
 
 TEST_P (AiksTest, CanRenderEmojiTextFrame)
 
 TEST_P (AiksTest, CanRenderEmojiTextFrameWithBlur)
 
 TEST_P (AiksTest, CanRenderEmojiTextFrameWithAlpha)
 
 TEST_P (AiksTest, CanRenderTextInSaveLayer)
 
 TEST_P (AiksTest, CanRenderTextOutsideBoundaries)
 
 TEST_P (AiksTest, TextRotated)
 
 TEST_P (AiksTest, CanDrawPaint)
 
 TEST_P (AiksTest, CanDrawPaintMultipleTimes)
 
 TEST_P (AiksTest, FormatWideGamut)
 
 TEST_P (AiksTest, FormatSRGB)
 
 TEST_P (AiksTest, TransformMultipliesCorrectly)
 
 TEST_P (AiksTest, FilledCirclesRenderCorrectly)
 
 TEST_P (AiksTest, StrokedCirclesRenderCorrectly)
 
 TEST_P (AiksTest, FilledEllipsesRenderCorrectly)
 
 TEST_P (AiksTest, FilledRoundRectsRenderCorrectly)
 
 TEST_P (AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly)
 
 TEST_P (AiksTest, FilledRoundRectPathsRenderCorrectly)
 
 TEST_P (AiksTest, CoverageOriginShouldBeAccountedForInSubpasses)
 
 TEST_P (AiksTest, SaveLayerDrawsBehindSubsequentEntities)
 
 TEST_P (AiksTest, SiblingSaveLayerBoundsAreRespected)
 
 TEST_P (AiksTest, CanRenderClippedLayers)
 
 TEST_P (AiksTest, SaveLayerFiltersScaleWithTransform)
 
 TEST_P (AiksTest, PaintWithFilters)
 
 TEST_P (AiksTest, OpacityPeepHoleApplicationTest)
 
 TEST_P (AiksTest, DrawPaintAbsorbsClears)
 
 TEST_P (AiksTest, ParentSaveLayerCreatesRenderPassWhenChildBackdropFilterIsPresent)
 
 TEST_P (AiksTest, DrawRectAbsorbsClears)
 
 TEST_P (AiksTest, DrawRectAbsorbsClearsNegativeRRect)
 
 TEST_P (AiksTest, DrawRectAbsorbsClearsNegativeRotation)
 
 TEST_P (AiksTest, DrawRectAbsorbsClearsNegative)
 
 TEST_P (AiksTest, ClipRectElidesNoOpClips)
 
 TEST_P (AiksTest, ClearColorOptimizationDoesNotApplyForBackdropFilters)
 
 TEST_P (AiksTest, CollapsedDrawPaintInSubpass)
 
 TEST_P (AiksTest, CollapsedDrawPaintInSubpassBackdropFilter)
 
 TEST_P (AiksTest, ColorMatrixFilterSubpassCollapseOptimization)
 
 TEST_P (AiksTest, LinearToSrgbFilterSubpassCollapseOptimization)
 
 TEST_P (AiksTest, SrgbToLinearFilterSubpassCollapseOptimization)
 
 TEST_P (AiksTest, TranslucentSaveLayerDrawsCorrectly)
 
 TEST_P (AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly)
 
 TEST_P (AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly)
 
 TEST_P (AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly)
 
 TEST_P (AiksTest, ImageFilteredSaveLayerWithUnboundedContents)
 
 TEST_P (AiksTest, ImageFilteredUnboundedSaveLayerWithUnboundedContents)
 
 TEST_P (AiksTest, TranslucentSaveLayerImageDrawsCorrectly)
 
 TEST_P (AiksTest, TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly)
 
 TEST_P (AiksTest, TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly)
 
 TEST_P (AiksTest, TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly)
 
 TEST_P (AiksTest, TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly)
 
 TEST_P (AiksTest, CanRenderTinyOverlappingSubpasses)
 
 TEST_P (AiksTest, CanRenderOffscreenCheckerboard)
 
 TEST_P (AiksTest, OpaqueEntitiesGetCoercedToSource)
 
 TEST_P (AiksTest, CanRenderDestructiveSaveLayer)
 
 TEST_P (AiksTest, CanRenderClippedRuntimeEffects)
 
 TEST_P (AiksTest, DrawPaintTransformsBounds)
 
 TEST_P (AiksTest, CanDrawPoints)
 
 TEST_P (AiksTest, DrawAtlasWithColorAdvancedAndTransform)
 
 TEST_P (AiksTest, DrawAtlasAdvancedAndTransform)
 
 TEST_P (AiksTest, CanDrawPointsWithTextureMap)
 
 TEST_P (AiksTest, TextForegroundShaderWithTransform)
 
 TEST_P (AiksTest, MatrixSaveLayerFilter)
 
 TEST_P (AiksTest, MatrixBackdropFilter)
 
 TEST_P (AiksTest, SolidColorApplyColorFilter)
 
 TEST_P (AiksTest, DrawScaledTextWithPerspectiveNoSaveLayer)
 
 TEST_P (AiksTest, DrawScaledTextWithPerspectiveSaveLayer)
 
 TEST_P (AiksTest, PipelineBlendSingleParameter)
 
 TEST_P (AiksTest, CaptureContext)
 
 TEST_P (AiksTest, CaptureInactivatedByDefault)
 
 TEST_P (AiksTest, ReleasesTextureOnTeardown)
 
 TEST_P (AiksTest, VerticesGeometryUVPositionData)
 
 TEST_P (AiksTest, VerticesGeometryUVPositionDataWithTranslate)
 
 TEST_P (AiksTest, VerticesGeometryColorUVPositionData)
 
 TEST_P (AiksTest, VerticesGeometryColorUVPositionDataAdvancedBlend)
 
 TEST_P (AiksTest, MatrixImageFilterMagnify)
 
 TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen)
 
 TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen)
 
 TEST_P (AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass)
 
 TEST_P (AiksTest, EmptySaveLayerIgnoresPaint)
 
 TEST_P (AiksTest, EmptySaveLayerRendersWithClear)
 
 TEST_P (AiksTest, SubpassWithClearColorOptimization)
 
 TEST_P (AiksTest, ImageColorSourceEffectTransform)
 
 TEST_P (AiksTest, CorrectClipDepthAssignedToEntities)
 
 TEST_P (AiksTest, CanDrawPerspectiveTransformWithClips)
 
 TEST_P (AiksTest, CanRenderClippedBackdropFilter)
 
 TEST_P (AiksTest, MipmapGenerationWorksCorrectly)
 
 TEST_P (AiksTest, DrawAtlasPlusWideGamut)
 
 TEST_P (AiksTest, StrokedPathWithMoveToThenCloseDrawnCorrectly)
 
 TEST (CanvasRecorder, Save)
 
 TEST (CanvasRecorder, SaveLayer)
 
 TEST (CanvasRecorder, Restore)
 
 TEST (CanvasRecorder, RestoreToCount)
 
 TEST (CanvasRecorder, ResetTransform)
 
 TEST (CanvasRecorder, Transform)
 
 TEST (CanvasRecorder, Concat)
 
 TEST (CanvasRecorder, PreConcat)
 
 TEST (CanvasRecorder, Translate)
 
 TEST (CanvasRecorder, Scale2)
 
 TEST (CanvasRecorder, Scale3)
 
 TEST (CanvasRecorder, Skew)
 
 TEST (CanvasRecorder, Rotate)
 
 TEST (CanvasRecorder, DrawPath)
 
 TEST (CanvasRecorder, DrawPaint)
 
 TEST (CanvasRecorder, DrawLine)
 
 TEST (CanvasRecorder, DrawRect)
 
 TEST (CanvasRecorder, DrawOval)
 
 TEST (CanvasRecorder, DrawRRect)
 
 TEST (CanvasRecorder, DrawCircle)
 
 TEST (CanvasRecorder, DrawPoints)
 
 TEST (CanvasRecorder, DrawImage)
 
 TEST (CanvasRecorder, DrawImageRect)
 
 TEST (CanvasRecorder, ClipPath)
 
 TEST (CanvasRecorder, ClipRect)
 
 TEST (CanvasRecorder, ClipOval)
 
 TEST (CanvasRecorder, ClipRRect)
 
 TEST (CanvasRecorder, DrawTextFrame)
 
 TEST (CanvasRecorder, DrawVertices)
 
 TEST (CanvasRecorder, DrawAtlas)
 
 TEST (AiksCanvasTest, EmptyCullRect)
 
 TEST (AiksCanvasTest, InitialCullRect)
 
 TEST (AiksCanvasTest, TranslatedCullRect)
 
 TEST (AiksCanvasTest, ScaledCullRect)
 
 TEST (AiksCanvasTest, RectClipIntersectAgainstEmptyCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffAgainstEmptyCullRect)
 
 TEST (AiksCanvasTest, RectClipIntersectAgainstCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffAgainstNonCoveredCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffAboveCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffBelowCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffLeftOfCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffRightOfCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffAgainstVCoveredCullRect)
 
 TEST (AiksCanvasTest, RectClipDiffAgainstHCoveredCullRect)
 
 TEST (AiksCanvasTest, RRectClipIntersectAgainstEmptyCullRect)
 
 TEST (AiksCanvasTest, RRectClipDiffAgainstEmptyCullRect)
 
 TEST (AiksCanvasTest, RRectClipIntersectAgainstCullRect)
 
 TEST (AiksCanvasTest, RRectClipDiffAgainstNonCoveredCullRect)
 
 TEST (AiksCanvasTest, RRectClipDiffAgainstVPartiallyCoveredCullRect)
 
 TEST (AiksCanvasTest, RRectClipDiffAgainstVFullyCoveredCullRect)
 
 TEST (AiksCanvasTest, RRectClipDiffAgainstHPartiallyCoveredCullRect)
 
 TEST (AiksCanvasTest, RRectClipDiffAgainstHFullyCoveredCullRect)
 
 TEST (AiksCanvasTest, PathClipIntersectAgainstEmptyCullRect)
 
 TEST (AiksCanvasTest, PathClipDiffAgainstEmptyCullRect)
 
 TEST (AiksCanvasTest, PathClipIntersectAgainstCullRect)
 
 TEST (AiksCanvasTest, PathClipDiffAgainstNonCoveredCullRect)
 
 TEST (AiksCanvasTest, PathClipDiffAgainstFullyCoveredCullRect)
 
 TEST (AiksCanvasTest, DisableLocalBoundsRectForFilteredSaveLayers)
 
 TEST (TraceSerializer, Save)
 
 TEST (ThreadTest, CanCreateMutex)
 
 TEST (ThreadTest, CanCreateMutexLock)
 
 TEST (ThreadTest, CanCreateRWMutex)
 
 TEST (ThreadTest, CanCreateRWMutexLock)
 
 TEST (StringsTest, CanSPrintF)
 
 TEST (ConditionVariableTest, WaitUntil)
 
 TEST (ConditionVariableTest, WaitFor)
 
 TEST (ConditionVariableTest, WaitForever)
 
 TEST (ConditionVariableTest, TestsCriticalSectionAfterWaitForUntil)
 
 TEST (ConditionVariableTest, TestsCriticalSectionAfterWait)
 
 TEST (BaseTest, NoExceptionPromiseValue)
 
 TEST (BaseTest, NoExceptionPromiseEmpty)
 
 TEST (BaseTest, CanUseTypedMasks)
 
 TEST (AllocatorTest, TextureDescriptorCompatibility)
 
flutter::DlColor toColor (const float *components)
 
 INSTANTIATE_PLAYGROUND_SUITE (DisplayListTest)
 
 TEST_P (DisplayListTest, CanDrawRect)
 
 TEST_P (DisplayListTest, CanDrawTextBlob)
 
 TEST_P (DisplayListTest, CanDrawTextBlobWithGradient)
 
 TEST_P (DisplayListTest, CanDrawTextWithSaveLayer)
 
 TEST_P (DisplayListTest, CanDrawImage)
 
 TEST_P (DisplayListTest, CanDrawCapsAndJoins)
 
 TEST_P (DisplayListTest, CanDrawArc)
 
 TEST_P (DisplayListTest, StrokedPathsDrawCorrectly)
 
 TEST_P (DisplayListTest, CanDrawWithOddPathWinding)
 
 TEST_P (DisplayListTest, CanDrawAnOpenPath)
 
 TEST_P (DisplayListTest, CanDrawWithMaskBlur)
 
 TEST_P (DisplayListTest, CanDrawStrokedText)
 
 TEST_P (DisplayListTest, StrokedTextNotOffsetFromNormalText)
 
 TEST_P (DisplayListTest, IgnoreMaskFilterWhenSavingLayer)
 
 TEST_P (DisplayListTest, CanDrawWithBlendColorFilter)
 
 TEST_P (DisplayListTest, CanDrawWithColorFilterImageFilter)
 
 TEST_P (DisplayListTest, CanDrawWithImageBlurFilter)
 
 TEST_P (DisplayListTest, CanDrawWithComposeImageFilter)
 
 TEST_P (DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter)
 
 TEST_P (DisplayListTest, CanDrawBackdropFilter)
 
 TEST_P (DisplayListTest, CanDrawNinePatchImage)
 
 TEST_P (DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest)
 
 TEST_P (DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest)
 
 TEST_P (DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest)
 
 TEST_P (DisplayListTest, CanDrawNinePatchImageCornersScaledDown)
 
 TEST_P (DisplayListTest, NinePatchImagePrecision)
 
 TEST_P (DisplayListTest, CanDrawPoints)
 
 TEST_P (DisplayListTest, CanDrawZeroLengthLine)
 
 TEST_P (DisplayListTest, CanDrawShadow)
 
 TEST_P (DisplayListTest, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists)
 
 TEST_P (DisplayListTest, TransparentShadowProducesCorrectColor)
 
 TEST_P (DisplayListTest, CanConvertTriangleFanToTriangles)
 
 TEST_P (DisplayListTest, CanDrawZeroWidthLine)
 
 TEST_P (DisplayListTest, CanDrawWithMatrixFilter)
 
 TEST_P (DisplayListTest, CanDrawWithMatrixFilterWhenSavingLayer)
 
 TEST_P (DisplayListTest, CanDrawRectWithLinearToSrgbColorFilter)
 
 TEST_P (DisplayListTest, CanDrawPaintWithColorSource)
 
 TEST_P (DisplayListTest, CanBlendDstOverAndDstCorrectly)
 
 TEST_P (DisplayListTest, CanDrawCorrectlyWithColorFilterAndImageFilter)
 
 TEST_P (DisplayListTest, MaskBlursApplyCorrectlyToColorSources)
 
 TEST_P (DisplayListTest, DrawVerticesSolidColorTrianglesWithoutIndices)
 
 TEST_P (DisplayListTest, DrawVerticesLinearGradientWithoutIndices)
 
 TEST_P (DisplayListTest, DrawVerticesLinearGradientWithTextureCoordinates)
 
 TEST_P (DisplayListTest, DrawVerticesImageSourceWithTextureCoordinates)
 
 TEST_P (DisplayListTest, DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending)
 
 TEST_P (DisplayListTest, DrawVerticesSolidColorTrianglesWithIndices)
 
 TEST_P (DisplayListTest, DrawVerticesPremultipliesColors)
 
 TEST_P (DisplayListTest, DrawShapes)
 
 TEST_P (DisplayListTest, ClipDrawRRectWithNonCircularRadii)
 
 TEST_P (DisplayListTest, DrawVerticesBlendModes)
 
template<typename Contents >
static std::optional< RectGetCoverageOfFirstEntity (const Picture &picture)
 
 TEST (DisplayListTest, RRectBoundsComputation)
 
 TEST (DisplayListTest, CircleBoundsComputation)
 
 TEST_P (DisplayListTest, DrawPaintIgnoresMaskFilter)
 
 TEST_P (DisplayListTest, DrawMaskBlursThatMightUseSaveLayers)
 
 TEST (SkiaConversionsTest, SkPointToPoint)
 
 TEST (SkiaConversionsTest, SkPointToSize)
 
 TEST (SkiaConversionsTest, ToColor)
 
 TEST (SkiaConversionsTest, GradientStopConversion)
 
 TEST (SkiaConversionsTest, GradientMissing0)
 
 TEST (SkiaConversionsTest, GradientMissingLastValue)
 
 TEST (SkiaConversionsTest, GradientStopGreaterThan1)
 
 TEST (SkiaConversionsTest, GradientConversionNonMonotonic)
 
 TEST_P (EntityTest, ClipContentsOptimizesFullScreenIntersectClips)
 
 TEST (ContentContext, CachesPipelines)
 
 TEST (ContentContext, InvalidatesAllPipelinesWithSameUniqueNameOnClear)
 
 TEST (ContentContext, InitializeCommonlyUsedShadersIfNeeded)
 
 INSTANTIATE_PLAYGROUND_SUITE (GaussianBlurFilterContentsTest)
 
 TEST (GaussianBlurFilterContentsTest, Create)
 
 TEST (GaussianBlurFilterContentsTest, CoverageEmpty)
 
 TEST (GaussianBlurFilterContentsTest, CoverageSimple)
 
 TEST (GaussianBlurFilterContentsTest, CoverageWithSigma)
 
 TEST_P (GaussianBlurFilterContentsTest, CoverageWithTexture)
 
 TEST_P (GaussianBlurFilterContentsTest, CoverageWithEffectTransform)
 
 TEST (GaussianBlurFilterContentsTest, FilterSourceCoverage)
 
 TEST (GaussianBlurFilterContentsTest, CalculateSigmaValues)
 
 TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverage)
 
 TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate)
 
 TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageRotated)
 
 TEST_P (GaussianBlurFilterContentsTest, CalculateUVsSimple)
 
 TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRect)
 
 TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRectScaled)
 
 TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithEffectTransform)
 
 TEST (GaussianBlurFilterContentsTest, CalculateSigmaForBlurRadius)
 
 TEST (GaussianBlurFilterContentsTest, Coefficients)
 
 TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesSimple)
 
 TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesComplex)
 
 TEST (FilterInputTest, CanSetLocalTransformForTexture)
 
 TEST (FilterInputTest, IsLeaf)
 
 TEST (FilterInputTest, SetCoverageInputs)
 
 INSTANTIATE_PLAYGROUND_SUITE (HostBufferTest)
 
 TEST_P (HostBufferTest, CanEmplace)
 
 TEST_P (HostBufferTest, CanEmplaceWithAlignment)
 
 TEST_P (HostBufferTest, HostBufferInitialState)
 
 TEST_P (HostBufferTest, ResetIncrementsFrameCounter)
 
 TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback)
 
 TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer)
 
 TEST_P (HostBufferTest, UnusedBuffersAreDiscardedWhenResetting)
 
 TEST_P (HostBufferTest, EmplaceWithProcIsAligned)
 
 TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipeline)
 
 TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES)
 
 TEST_P (EntityPassTargetTest, SwapWithMSAATexture)
 
 TEST_P (EntityPassTargetTest, SwapWithMSAAImplicitResolve)
 
 TEST (EntityPassClipStackTest, CanPushAndPopEntities)
 
 TEST (EntityPassClipStackTest, CanPopEntitiesSafely)
 
 TEST (EntityPassClipStackTest, CanAppendNoChange)
 
 TEST (EntityPassClipStackTest, AppendCoverageNoChange)
 
 TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverage)
 
 TEST (EntityPassClipStackTest, UnbalancedRestore)
 
 TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpasses)
 
 TEST_P (EntityTest, CanCreateEntity)
 
auto CreatePassWithRectPath (Rect rect, std::optional< Rect > bounds_hint, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, bool collapse=false)
 
 TEST_P (EntityTest, EntityPassRespectsUntrustedSubpassBoundsLimit)
 
 TEST_P (EntityTest, EntityPassTrustsSnugSubpassBoundsLimit)
 
 TEST_P (EntityTest, EntityPassCanMergeSubpassIntoParent)
 
 TEST_P (EntityTest, EntityPassCoverageRespectsCoverageLimit)
 
 TEST_P (EntityTest, FilterCoverageRespectsCropRect)
 
 TEST_P (EntityTest, CanDrawRect)
 
 TEST_P (EntityTest, CanDrawRRect)
 
 TEST_P (EntityTest, GeometryBoundsAreTransformed)
 
 TEST_P (EntityTest, ThreeStrokesInOnePath)
 
 TEST_P (EntityTest, StrokeWithTextureContents)
 
 TEST_P (EntityTest, TriangleInsideASquare)
 
 TEST_P (EntityTest, StrokeCapAndJoinTest)
 
 TEST_P (EntityTest, CubicCurveTest)
 
 TEST_P (EntityTest, CanDrawCorrectlyWithRotatedTransform)
 
 TEST_P (EntityTest, CubicCurveAndOverlapTest)
 
 TEST_P (EntityTest, SolidColorContentsStrokeSetStrokeCapsAndJoins)
 
 TEST_P (EntityTest, SolidColorContentsStrokeSetMiterLimit)
 
 TEST_P (EntityTest, BlendingModeOptions)
 
 TEST_P (EntityTest, BezierCircleScaled)
 
 TEST_P (EntityTest, Filters)
 
 TEST_P (EntityTest, GaussianBlurFilter)
 
 TEST_P (EntityTest, MorphologyFilter)
 
 TEST_P (EntityTest, SetBlendMode)
 
 TEST_P (EntityTest, ContentsGetBoundsForEmptyPathReturnsNullopt)
 
 TEST_P (EntityTest, SolidStrokeCoverageIsCorrect)
 
 TEST_P (EntityTest, BorderMaskBlurCoverageIsCorrect)
 
 TEST_P (EntityTest, DrawAtlasNoColor)
 
 TEST_P (EntityTest, DrawAtlasWithColorAdvanced)
 
 TEST_P (EntityTest, DrawAtlasWithColorSimple)
 
 TEST_P (EntityTest, DrawAtlasUsesProvidedCullRectForCoverage)
 
 TEST_P (EntityTest, DrawAtlasWithOpacity)
 
 TEST_P (EntityTest, DrawAtlasNoColorFullSize)
 
 TEST_P (EntityTest, SolidFillCoverageIsCorrect)
 
 TEST_P (EntityTest, SolidFillShouldRenderIsCorrect)
 
 TEST_P (EntityTest, DoesNotCullEntitiesByDefault)
 
 TEST_P (EntityTest, ClipContentsShouldRenderIsCorrect)
 
 TEST_P (EntityTest, ClipContentsGetClipCoverageIsCorrect)
 
 TEST_P (EntityTest, RRectShadowTest)
 
 TEST_P (EntityTest, ColorMatrixFilterCoverageIsCorrect)
 
 TEST_P (EntityTest, ColorMatrixFilterEditable)
 
 TEST_P (EntityTest, LinearToSrgbFilterCoverageIsCorrect)
 
 TEST_P (EntityTest, LinearToSrgbFilter)
 
 TEST_P (EntityTest, SrgbToLinearFilterCoverageIsCorrect)
 
 TEST_P (EntityTest, SrgbToLinearFilter)
 
static Vector3 RGBToYUV (Vector3 rgb, YUVColorSpace yuv_color_space)
 
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures (Context *context, YUVColorSpace yuv_color_space)
 
 TEST_P (EntityTest, YUVToRGBFilter)
 
 TEST_P (EntityTest, RuntimeEffect)
 
 TEST_P (EntityTest, RuntimeEffectCanSuccessfullyRender)
 
 TEST_P (EntityTest, RuntimeEffectCanPrecache)
 
 TEST_P (EntityTest, RuntimeEffectSetsRightSizeWhenUniformIsStruct)
 
 TEST_P (EntityTest, InheritOpacityTest)
 
 TEST_P (EntityTest, ColorFilterWithForegroundColorAdvancedBlend)
 
 TEST_P (EntityTest, ColorFilterWithForegroundColorClearBlend)
 
 TEST_P (EntityTest, ColorFilterWithForegroundColorSrcBlend)
 
 TEST_P (EntityTest, ColorFilterWithForegroundColorDstBlend)
 
 TEST_P (EntityTest, ColorFilterWithForegroundColorSrcInBlend)
 
 TEST_P (EntityTest, CoverageForStrokePathWithNegativeValuesInTransform)
 
 TEST_P (EntityTest, SolidColorContentsIsOpaque)
 
 TEST_P (EntityTest, ConicalGradientContentsIsOpaque)
 
 TEST_P (EntityTest, LinearGradientContentsIsOpaque)
 
 TEST_P (EntityTest, RadialGradientContentsIsOpaque)
 
 TEST_P (EntityTest, SweepGradientContentsIsOpaque)
 
 TEST_P (EntityTest, TiledTextureContentsIsOpaque)
 
 TEST_P (EntityTest, PointFieldGeometryCoverage)
 
 TEST_P (EntityTest, ColorFilterContentsWithLargeGeometry)
 
 TEST_P (EntityTest, TextContentsCeilsGlyphScaleToDecimal)
 
 TEST_P (EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass)
 
 TEST_P (EntityTest, SpecializationConstantsAreAppliedToVariants)
 
 TEST_P (EntityTest, DecalSpecializationAppliedToMorphologyFilter)
 
 TEST_P (EntityTest, ContentContextOptionsHasReasonableHashFunctions)
 
 TEST_P (EntityTest, FillPathGeometryGetPositionBufferReturnsExpectedMode)
 
 TEST_P (EntityTest, FailOnValidationError)
 
 TEST_P (EntityTest, CanComputeGeometryForEmptyPathsWithoutCrashing)
 
 TEST_P (EntityTest, CanRenderEmptyPathsWithoutCrashing)
 
 TEST (EntityGeometryTest, RectGeometryCoversArea)
 
 TEST (EntityGeometryTest, FillPathGeometryCoversArea)
 
 TEST (EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect)
 
 TEST (EntityGeometryTest, LineGeometryCoverage)
 
 TEST (EntityGeometryTest, RoundRectGeometryCoversArea)
 
 TEST (EntityGeometryTest, GeometryResultHasReasonableDefaults)
 
 TEST_P (RenderTargetCacheTest, CachesUsedTexturesAcrossFrames)
 
 TEST_P (RenderTargetCacheTest, DoesNotPersistFailedAllocations)
 
 TEST_P (RenderTargetCacheTest, CachedTextureGetsNewAttachmentConfig)
 
 TEST_P (RenderTargetCacheTest, CreateWithEmptySize)
 
 TEST (GeometryTest, ScalarNearlyEqual)
 
 TEST (GeometryTest, MakeColumn)
 
 TEST (GeometryTest, MakeRow)
 
 TEST (GeometryTest, RotationMatrix)
 
 TEST (GeometryTest, InvertMultMatrix)
 
 TEST (GeometryTest, MatrixBasis)
 
 TEST (GeometryTest, MutliplicationMatrix)
 
 TEST (GeometryTest, DeterminantTest)
 
 TEST (GeometryTest, InvertMatrix)
 
 TEST (GeometryTest, TestDecomposition)
 
 TEST (GeometryTest, TestDecomposition2)
 
 TEST (GeometryTest, TestRecomposition)
 
 TEST (GeometryTest, TestRecomposition2)
 
 TEST (GeometryTest, MatrixVectorMultiplication)
 
 TEST (GeometryTest, MatrixMakeRotationFromQuaternion)
 
 TEST (GeometryTest, MatrixTransformDirection)
 
 TEST (GeometryTest, MatrixGetMaxBasisLength)
 
 TEST (GeometryTest, MatrixGetMaxBasisLengthXY)
 
 TEST (GeometryTest, MatrixMakeOrthographic)
 
 TEST (GeometryTest, MatrixMakePerspective)
 
 TEST (GeometryTest, MatrixGetBasisVectors)
 
 TEST (GeometryTest, MatrixGetDirectionScale)
 
 TEST (GeometryTest, MatrixTranslationScaleOnly)
 
 TEST (GeometryTest, MatrixLookAt)
 
 TEST (GeometryTest, QuaternionLerp)
 
 TEST (GeometryTest, QuaternionVectorMultiply)
 
 TEST (GeometryTest, CanGenerateMipCounts)
 
 TEST (GeometryTest, CanConvertTTypesExplicitly)
 
 TEST (GeometryTest, CanPerformAlgebraicPointOps)
 
 TEST (GeometryTest, CanPerformAlgebraicPointOpsWithArithmeticTypes)
 
 TEST (GeometryTest, PointIntegerCoercesToFloat)
 
 TEST (GeometryTest, SizeCoercesToPoint)
 
 TEST (GeometryTest, CanUsePointAssignmentOperators)
 
 TEST (GeometryTest, PointDotProduct)
 
 TEST (GeometryTest, PointCrossProduct)
 
 TEST (GeometryTest, PointReflect)
 
 TEST (GeometryTest, PointAbs)
 
 TEST (GeometryTest, PointAngleTo)
 
 TEST (GeometryTest, PointMin)
 
 TEST (GeometryTest, Vector3Min)
 
 TEST (GeometryTest, Vector4Min)
 
 TEST (GeometryTest, PointMax)
 
 TEST (GeometryTest, Vector3Max)
 
 TEST (GeometryTest, Vector4Max)
 
 TEST (GeometryTest, PointFloor)
 
 TEST (GeometryTest, Vector3Floor)
 
 TEST (GeometryTest, Vector4Floor)
 
 TEST (GeometryTest, PointCeil)
 
 TEST (GeometryTest, Vector3Ceil)
 
 TEST (GeometryTest, Vector4Ceil)
 
 TEST (GeometryTest, PointRound)
 
 TEST (GeometryTest, Vector3Round)
 
 TEST (GeometryTest, Vector4Round)
 
 TEST (GeometryTest, PointLerp)
 
 TEST (GeometryTest, Vector3Lerp)
 
 TEST (GeometryTest, Vector4Lerp)
 
 TEST (GeometryTest, CanUseVector3AssignmentOperators)
 
 TEST (GeometryTest, CanPerformAlgebraicVector3Ops)
 
 TEST (GeometryTest, CanPerformAlgebraicVector3OpsWithArithmeticTypes)
 
 TEST (GeometryTest, ColorPremultiply)
 
 TEST (GeometryTest, ColorR8G8B8A8)
 
 TEST (GeometryTest, ColorLerp)
 
 TEST (GeometryTest, ColorClamp01)
 
 TEST (GeometryTest, ColorMakeRGBA8)
 
 TEST (GeometryTest, ColorApplyColorMatrix)
 
 TEST (GeometryTest, ColorLinearToSRGB)
 
 TEST (GeometryTest, ColorSRGBToLinear)
 
 TEST (GeometryTest, ColorBlendReturnsExpectedResults)
 
 TEST (GeometryTest, BlendModeToString)
 
 TEST (GeometryTest, CanConvertBetweenDegressAndRadians)
 
 TEST (GeometryTest, MatrixPrinting)
 
 TEST (GeometryTest, PointPrinting)
 
 TEST (GeometryTest, Vector3Printing)
 
 TEST (GeometryTest, Vector4Printing)
 
 TEST (GeometryTest, ColorPrinting)
 
 TEST (GeometryTest, ToIColor)
 
 TEST (GeometryTest, Gradient)
 
 TEST (GeometryTest, HalfConversions)
 
 TEST (MatrixTest, Multiply)
 
 TEST (MatrixTest, HasPerspective2D)
 
 TEST (MatrixTest, HasPerspective)
 
 TEST (MatrixTest, IsAligned2D)
 
 TEST (MatrixTest, IsAligned)
 
 TEST (MatrixTest, TransformHomogenous)
 
 TEST (PathTest, CubicPathComponentPolylineDoesNotIncludePointOne)
 
 TEST (PathTest, PathCreatePolyLineDoesNotDuplicatePoints)
 
 TEST (PathTest, PathBuilderSetsCorrectContourPropertiesForAddCommands)
 
 TEST (PathTest, PathCreatePolylineGeneratesCorrectContourData)
 
 TEST (PathTest, PolylineGetContourPointBoundsReturnsCorrectRanges)
 
 TEST (PathTest, PathAddRectPolylineHasCorrectContourData)
 
 TEST (PathTest, PathPolylineDuplicatesAreRemovedForSameContour)
 
 TEST (PathTest, PolylineBufferReuse)
 
 TEST (PathTest, PolylineFailsWithNullptrBuffer)
 
 TEST (PathTest, PathShifting)
 
 TEST (PathTest, PathBuilderWillComputeBounds)
 
 TEST (PathTest, PathHorizontalLine)
 
 TEST (PathTest, PathVerticalLine)
 
 TEST (PathTest, QuadradicPath)
 
 TEST (PathTest, CubicPath)
 
 TEST (PathTest, BoundingBoxCubic)
 
 TEST (PathTest, BoundingBoxOfCompositePathIsCorrect)
 
 TEST (PathTest, ExtremaOfCubicPathComponentIsCorrect)
 
 TEST (PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect)
 
 TEST (PathTest, EmptyPath)
 
 TEST (PathTest, SimplePath)
 
 TEST (PathTest, RepeatCloseDoesNotAddNewLines)
 
 TEST (PathTest, CloseAfterMoveDoesNotAddNewLines)
 
 TEST (PathTest, CloseAtOriginDoesNotAddNewLineSegment)
 
 TEST (PathTest, CanBeCloned)
 
 TEST (PathTest, PathBuilderDoesNotMutateCopiedPaths)
 
 TEST (RectTest, RectEmptyDeclaration)
 
 TEST (RectTest, IRectEmptyDeclaration)
 
 TEST (RectTest, RectDefaultConstructor)
 
 TEST (RectTest, IRectDefaultConstructor)
 
 TEST (RectTest, RectSimpleLTRB)
 
 TEST (RectTest, IRectSimpleLTRB)
 
 TEST (RectTest, RectSimpleXYWH)
 
 TEST (RectTest, IRectSimpleXYWH)
 
 TEST (RectTest, RectOverflowXYWH)
 
 TEST (RectTest, IRectOverflowXYWH)
 
 TEST (RectTest, RectOverflowLTRB)
 
 TEST (RectTest, IRectOverflowLTRB)
 
 TEST (RectTest, RectMakeSize)
 
 TEST (RectTest, RectMakeMaximum)
 
 TEST (RectTest, IRectMakeMaximum)
 
 TEST (RectTest, RectFromRect)
 
 TEST (RectTest, IRectFromIRect)
 
 TEST (RectTest, RectCopy)
 
 TEST (RectTest, IRectCopy)
 
 TEST (RectTest, RectOriginSizeXYWHGetters)
 
 TEST (RectTest, IRectOriginSizeXYWHGetters)
 
 TEST (RectTest, RectRoundOutEmpty)
 
 TEST (RectTest, RectRoundOutSimple)
 
 TEST (RectTest, RectRoundOutToIRectHuge)
 
 TEST (RectTest, RectDoesNotIntersectEmpty)
 
 TEST (RectTest, IRectDoesNotIntersectEmpty)
 
 TEST (RectTest, EmptyRectDoesNotIntersect)
 
 TEST (RectTest, EmptyIRectDoesNotIntersect)
 
 TEST (RectTest, RectScale)
 
 TEST (RectTest, IRectScale)
 
 TEST (RectTest, RectArea)
 
 TEST (RectTest, IRectArea)
 
 TEST (RectTest, RectGetNormalizingTransform)
 
 TEST (RectTest, IRectGetNormalizingTransform)
 
 TEST (RectTest, RectXYWHIsEmpty)
 
 TEST (RectTest, IRectXYWHIsEmpty)
 
 TEST (RectTest, MakePointBoundsQuad)
 
 TEST (RectTest, IsSquare)
 
 TEST (RectTest, GetCenter)
 
 TEST (RectTest, RectExpand)
 
 TEST (RectTest, IRectExpand)
 
 TEST (RectTest, ContainsFloatingPoint)
 
template<typename R >
static constexpr R flip_lr (R rect)
 
template<typename R >
static constexpr R flip_tb (R rect)
 
template<typename R >
static constexpr R flip_lrtb (R rect)
 
static constexpr Rect swap_nan (const Rect &rect, int index)
 
static constexpr Point swap_nan (const Point &point, int index)
 
 TEST (RectTest, RectUnion)
 
 TEST (RectTest, OptRectUnion)
 
 TEST (RectTest, IRectUnion)
 
 TEST (RectTest, OptIRectUnion)
 
 TEST (RectTest, RectIntersection)
 
 TEST (RectTest, OptRectIntersection)
 
 TEST (RectTest, IRectIntersection)
 
 TEST (RectTest, OptIRectIntersection)
 
 TEST (RectTest, RectIntersectsWithRect)
 
 TEST (RectTest, IRectIntersectsWithRect)
 
 TEST (RectTest, RectContainsPoint)
 
 TEST (RectTest, IRectContainsIPoint)
 
 TEST (RectTest, RectContainsRect)
 
 TEST (RectTest, IRectContainsIRect)
 
 TEST (RectTest, RectCutOut)
 
 TEST (RectTest, IRectCutOut)
 
 TEST (RectTest, RectGetPoints)
 
 TEST (RectTest, RectShift)
 
 TEST (RectTest, RectGetTransformedPoints)
 
 TEST (RectTest, RectMakePointBounds)
 
 TEST (RectTest, RectGetPositive)
 
 TEST (RectTest, RectDirections)
 
 TEST (RectTest, RectProject)
 
 TEST (RectTest, RectRoundOut)
 
 TEST (RectTest, IRectRoundOut)
 
 TEST (RectTest, RectRound)
 
 TEST (RectTest, IRectRound)
 
 TEST (RectTest, TransformAndClipBounds)
 
 TEST (SaturatedMath, ExplicitAddOfSignedInts)
 
 TEST (SaturatedMath, ImplicitAddOfSignedInts)
 
 TEST (SaturatedMath, ExplicitAddOfFloatingPoint)
 
 TEST (SaturatedMath, ImplicitAddOfFloatingPoint)
 
 TEST (SaturatedMath, ExplicitSubOfSignedInts)
 
 TEST (SaturatedMath, ImplicitSubOfSignedInts)
 
 TEST (SaturatedMath, ExplicitSubOfFloatingPoint)
 
 TEST (SaturatedMath, ImplicitSubOfFloatingPoint)
 
 TEST (SaturatedMath, ExplicitAverageScalarOfSignedInts)
 
 TEST (SaturatedMath, ImplicitAverageScalarOfSignedInts)
 
 TEST (SaturatedMath, ExplicitAverageScalarOfFloatingPoint)
 
 TEST (SaturatedMath, ImplicitAverageScalarOfFloatingPoint)
 
 TEST (SaturatedMath, CastingFiniteDoubleToFloatStaysFinite)
 
 TEST (SaturatedMath, CastingInfiniteDoubleToFloatStaysInfinite)
 
 TEST (SaturatedMath, CastingNaNDoubleToFloatStaysNaN)
 
 TEST (SaturatedMath, CastingLargeScalarToSignedIntProducesLimit)
 
 TEST (SaturatedMath, CastingInfiniteScalarToSignedIntProducesLimit)
 
 TEST (SaturatedMath, CastingNaNScalarToSignedIntProducesZero)
 
 TEST (SizeTest, SizeIsEmpty)
 
 TEST (SizeTest, ISizeIsEmpty)
 
 TEST (SizeTest, IsSquare)
 
 TEST (SizeTest, MaxDimension)
 
 TEST (SizeTest, NegationOperator)
 
 TEST (TrigTest, TrigAngles)
 
 TEST (TrigTest, MultiplyByScalarRadius)
 
 TEST_F (GoldenTests, ConicalGradient)
 
 TEST (CapabilitiesGLES, CanInitializeWithDefaults)
 
 TEST (CapabilitiesGLES, SupportsDecalSamplerAddressMode)
 
 TEST (CapabilitiesGLES, SupportsDecalSamplerAddressModeNotOES)
 
 TEST (CapabilitiesGLES, SupportsFramebufferFetch)
 
 TEST (FormatsGLES, CanFormatFramebufferErrorMessage)
 
void RecordGLCall (const char *name)
 
void doNothing ()
 
const unsigned char * mockGetString (GLenum name)
 
const unsigned char * mockGetStringi (GLenum name, GLuint index)
 
void mockGetIntegerv (GLenum name, int *value)
 
GLenum mockGetError ()
 
void mockPopDebugGroupKHR ()
 
void mockPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message)
 
void mockGenQueriesEXT (GLsizei n, GLuint *ids)
 
void mockBeginQueryEXT (GLenum target, GLuint id)
 
void mockEndQueryEXT (GLuint id)
 
void mockGetQueryObjectuivEXT (GLuint id, GLenum target, GLuint *result)
 
void mockGetQueryObjectui64vEXT (GLuint id, GLenum target, GLuint64 *result)
 
void mockDeleteQueriesEXT (GLsizei size, const GLuint *queries)
 
 TEST (MockGLES, CanInitialize)
 
 TEST (MockGLES, CapturesPushAndPopDebugGroup)
 
 TEST (MockGLES, CanCallUnmockedFunction)
 
 TEST (ProcTableGLES, ResolvesCorrectClearDepthProcOnES)
 
 TEST (ProcTableGLES, ResolvesCorrectClearDepthProcOnDesktopGL)
 
 TEST (SpecConstant, CanCreateShaderWithSpecializationConstant)
 
 TEST (SpecConstant, CanCreateShaderWithSpecializationConstantMultipleValues)
 
 TEST (TextureMTL, CreateFromDrawable)
 
 TEST (AllocatorVKTest, ToVKImageUsageFlags)
 
 TEST (AllocatorVKTest, MemoryTypeSelectionSingleHeap)
 
 TEST (AllocatorVKTest, MemoryTypeSelectionTwoHeap)
 
 TEST (BlitCommandVkTest, BlitCopyTextureToTextureCommandVK)
 
 TEST (BlitCommandVkTest, BlitCopyTextureToBufferCommandVK)
 
 TEST (BlitCommandVkTest, BlitCopyBufferToTextureCommandVK)
 
 TEST (BlitCommandVkTest, BlitGenerateMipmapCommandVK)
 
 TEST (CommandEncoderVKTest, DeleteEncoderAfterThreadDies)
 
 TEST (CommandEncoderVKTest, CleanupAfterSubmit)
 
 TEST (CommandPoolRecyclerVKTest, GetsACommandPoolPerThread)
 
 TEST (CommandPoolRecyclerVKTest, GetsTheSameCommandPoolOnSameThread)
 
 TEST (CommandPoolRecyclerVKTest, ReclaimMakesCommandPoolAvailable)
 
 TEST (CommandPoolRecyclerVKTest, CommandBuffersAreRecycled)
 
 TEST (ContextVKTest, CommonHardwareConcurrencyConfigurations)
 
 TEST (ContextVKTest, DeletesCommandPools)
 
 TEST (ContextVKTest, DeletesCommandPoolsOnAllThreads)
 
 TEST (ContextVKTest, DeletePipelineAfterContext)
 
 TEST (ContextVKTest, DeleteShaderFunctionAfterContext)
 
 TEST (ContextVKTest, DeletePipelineLibraryAfterContext)
 
 TEST (ContextVKTest, CanCreateContextInAbsenceOfValidationLayers)
 
 TEST (ContextVKTest, CanCreateContextWithValidationLayers)
 
 TEST (CapabilitiesVKTest, ContextInitializesWithNoStencilFormat)
 
 TEST (CapabilitiesVKTest, ContextFailsInitializationForNoCombinedDepthStencilFormat)
 
 TEST (ContextVKTest, WarmUpFunctionCreatesRenderPass)
 
 TEST (ContextVKTest, FatalMissingValidations)
 
 TEST (ContextVKTest, HasDefaultColorFormat)
 
 TEST (DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools)
 
 TEST (DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable)
 
 TEST (DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded)
 
 INSTANTIATE_VULKAN_PLAYGROUND_SUITE (DriverInfoVKTest)
 
 TEST_P (DriverInfoVKTest, CanQueryDriverInfo)
 
 TEST_P (DriverInfoVKTest, CanDumpToLog)
 
 TEST (FenceWaiterVKTest, IgnoresNullFence)
 
 TEST (FenceWaiterVKTest, IgnoresNullCallback)
 
 TEST (FenceWaiterVKTest, ExecutesFenceCallback)
 
 TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
 
 TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
 
 TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
 
 TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
 
 TEST (RenderPassBuilder, CreatesRenderPassWithNoDepthStencil)
 
 TEST (RenderPassBuilder, CreatesRenderPassWithCombinedDepthStencil)
 
 TEST (RenderPassBuilder, CreatesRenderPassWithOnlyStencil)
 
 TEST (RenderPassBuilder, CreatesMSAAResolveWithCorrectStore)
 
 TEST_P (RendererTest, CachesRenderPassAndFramebuffer)
 
 TEST (ResourceManagerVKTest, CreatesANewInstance)
 
 TEST (ResourceManagerVKTest, ReclaimMovesAResourceAndDestroysIt)
 
 TEST (ResourceManagerVKTest, TerminatesWhenOutOfScope)
 
 TEST (ResourceManagerVKTest, IsThreadSafe)
 
std::shared_ptr< std::vector< std::string > > GetMockVulkanFunctions (VkDevice device)
 
void SetSwapchainImageSize (ISize size)
 Override the image size returned by all swapchain images.
 
 TEST (MockVulkanContextTest, IsThreadSafe)
 
 TEST (MockVulkanContextTest, DefaultFenceAlwaysReportsSuccess)
 
 TEST (MockVulkanContextTest, MockedFenceReportsStatus)
 
vk::UniqueSurfaceKHR CreateSurface (const ContextVK &context)
 
 TEST (SwapchainTest, CanCreateSwapchain)
 
 TEST (SwapchainTest, RecreateSwapchainWhenSizeChanges)
 
 TEST (SwapchainTest, CachesRenderPassOnSwapchainImage)
 
 INSTANTIATE_PLAYGROUND_SUITE (BlitPassTest)
 
 TEST_P (BlitPassTest, BlitAcrossDifferentPixelFormatsFails)
 
 TEST_P (BlitPassTest, BlitAcrossDifferentSampleCountsFails)
 
 TEST_P (BlitPassTest, BlitPassesForMatchingFormats)
 
 CAPABILITY_TEST (SupportsOffscreenMSAA, false)
 
 CAPABILITY_TEST (SupportsSSBO, false)
 
 CAPABILITY_TEST (SupportsBufferToTextureBlits, false)
 
 CAPABILITY_TEST (SupportsTextureToTextureBlits, false)
 
 CAPABILITY_TEST (SupportsFramebufferFetch, false)
 
 CAPABILITY_TEST (SupportsCompute, false)
 
 CAPABILITY_TEST (SupportsComputeSubgroups, false)
 
 CAPABILITY_TEST (SupportsReadFromResolve, false)
 
 CAPABILITY_TEST (SupportsDecalSamplerAddressMode, false)
 
 CAPABILITY_TEST (SupportsDeviceTransientTextures, false)
 
 TEST (CapabilitiesTest, DefaultColorFormat)
 
 TEST (CapabilitiesTest, DefaultStencilFormat)
 
 TEST (CapabilitiesTest, DefaultDepthStencilFormat)
 
 TEST (CapabilitiesTest, DefaultGlyphAtlasFormat)
 
 INSTANTIATE_COMPUTE_SUITE (ComputeSubgroupTest)
 
 TEST_P (ComputeSubgroupTest, CapabilitiesSuportSubgroups)
 
 TEST_P (ComputeSubgroupTest, PathPlayground)
 
 TEST_P (ComputeSubgroupTest, LargePath)
 
 TEST_P (ComputeSubgroupTest, QuadAndCubicInOnePath)
 
 TEST_P (ComputeTest, CapabilitiesReportSupport)
 
 TEST_P (ComputeTest, CanCreateComputePass)
 
 TEST_P (ComputeTest, CanComputePrefixSum)
 
 TEST_P (ComputeTest, 1DThreadgroupSizingIsCorrect)
 
 TEST_P (ComputeTest, CanComputePrefixSumLargeInteractive)
 
 TEST_P (ComputeTest, MultiStageInputAndOutput)
 
 TEST_P (ComputeTest, CanCompute1DimensionalData)
 
 TEST_P (ComputeTest, ReturnsEarlyWhenAnyGridDimensionIsZero)
 
 TEST (PipelineDescriptorTest, PrimitiveTypeHashEquality)
 
 TEST (PoolTest, Simple)
 
 TEST (PoolTest, Overload)
 
static void InstantiateTestShaderLibrary (Context::BackendType backend_type)
 
 INSTANTIATE_PLAYGROUND_SUITE (RendererDartTest)
 
 TEST_P (RendererDartTest, CanRunDartInPlaygroundFrame)
 
 TEST_P (RendererDartTest, CanInstantiateFlutterGPUContext)
 
 TEST_P (RendererDartTest, CanCreateShaderLibrary)
 
 TEST_P (RendererDartTest, CanReflectUniformStructs)
 
 TEST_P (RendererDartTest, UniformBindFailsForInvalidHostBufferOffset)
 
 TEST_P (RendererDartTest, CanCreateRenderPassAndSubmit)
 
 TEST_P (RendererTest, CanCreateBoxPrimitive)
 
 TEST_P (RendererTest, CanRenderPerspectiveCube)
 
 TEST_P (RendererTest, CanRenderMultiplePrimitives)
 
 TEST_P (RendererTest, CanRenderToTexture)
 
 TEST_P (RendererTest, CanRenderInstanced)
 
 TEST_P (RendererTest, CanBlitTextureToTexture)
 
 TEST_P (RendererTest, CanBlitTextureToBuffer)
 
 TEST_P (RendererTest, CanGenerateMipmaps)
 
 TEST_P (RendererTest, TheImpeller)
 
 TEST_P (RendererTest, ArrayUniforms)
 
 TEST_P (RendererTest, InactiveUniforms)
 
 TEST_P (RendererTest, CanCreateCPUBackedTexture)
 
 TEST_P (RendererTest, DefaultIndexSize)
 
 TEST_P (RendererTest, DefaultIndexBehavior)
 
 TEST_P (RendererTest, VertexBufferBuilder)
 
static const CompareFunctionUIDataCompareFunctionUI ()
 
 TEST_P (RendererTest, StencilMask)
 
 TEST_P (RendererTest, CanLookupRenderTargetProperties)
 
 TEST_P (RendererTest, RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat)
 
template<class VertexShader , class FragmentShader >
std::shared_ptr< Pipeline< PipelineDescriptor > > CreateDefaultPipeline (const std::shared_ptr< Context > &context)
 
 TEST_P (RendererTest, CanSepiaToneWithSubpasses)
 
 TEST_P (RendererTest, CanSepiaToneThenSwizzleWithSubpasses)
 
 INSTANTIATE_PLAYGROUND_SUITE (RuntimeStageTest)
 
 TEST_P (RuntimeStageTest, CanReadValidBlob)
 
 TEST_P (RuntimeStageTest, CanRejectInvalidBlob)
 
 TEST_P (RuntimeStageTest, CanReadUniforms)
 
 TEST_P (RuntimeStageTest, CanRegisterStage)
 
 TEST_P (RuntimeStageTest, CanCreatePipelineFromRuntimeStage)
 
 TEST_P (RuntimeStageTest, ContainsExpectedShaderTypes)
 
static std::shared_ptr< fml::MappingCreateMappingFromString (std::string p_string)
 
const std::string CreateStringFromMapping (const fml::Mapping &mapping)
 
 TEST (ShaderArchiveTest, CanReadAndWriteBlobs)
 
 TEST (ShaderArchiveTest, ArchiveAndMultiArchiveHaveDifferentIdentifiers)
 
 TEST (TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus)
 
 TEST (TessellatorTest, TessellateConvex)
 
 TEST (TessellatorTest, CircleVertexCounts)
 
 TEST (TessellatorTest, FilledCircleTessellationVertices)
 
 TEST (TessellatorTest, StrokedCircleTessellationVertices)
 
 TEST (TessellatorTest, RoundCapLineTessellationVertices)
 
 TEST (TessellatorTest, FilledEllipseTessellationVertices)
 
 TEST (TessellatorTest, FilledRoundRectTessellationVertices)
 
 TEST (TessellatorTest, EarlyReturnEmptyConvexShape)
 
 TEST (TessellatorTest, ChecksConcurrentPolylineUsage)
 
static std::shared_ptr< GlyphAtlasCreateGlyphAtlas (Context &context, const TypographerContext *typographer_context, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
 
 TEST_P (TypographerTest, CanConvertTextBlob)
 
 TEST_P (TypographerTest, CanCreateRenderContext)
 
 TEST_P (TypographerTest, CanCreateGlyphAtlas)
 
 TEST_P (TypographerTest, LazyAtlasTracksColor)
 
 TEST_P (TypographerTest, GlyphAtlasWithOddUniqueGlyphSize)
 
 TEST_P (TypographerTest, GlyphAtlasIsRecycledIfUnchanged)
 
 TEST_P (TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize)
 
 TEST_P (TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged)
 
 TEST_P (TypographerTest, GlyphAtlasTextureIsRecreatedIfTypeChanges)
 
 TEST_P (TypographerTest, MaybeHasOverlapping)
 
 TEST_P (TypographerTest, RectanglePackerAddsNonoverlapingRectangles)
 
 TEST_P (TypographerTest, GlyphAtlasTextureIsRecycledWhenContentsAreNotRecreated)
 

Variables

static const std::map< std::string, MaskBlurTestConfigkPaintVariations
 
static constexpr std::string_view kFontFixture
 
std::vector< Pointgolden_cubic_and_quad_points
 
static std::mutex g_test_lock
 
static std::weak_ptr< MockGLESg_mock_gles
 
static ProcTableGLES::Resolver g_resolver
 
static std::vector< const unsigned char * > g_extensions
 
static const unsigned char * g_version
 
auto const kMockVendor = (unsigned char*)"MockGLES"
 
const auto kMockShadingLanguageVersion = (unsigned char*)"GLSL ES 1.0"
 
auto const kExtensions
 
const ProcTableGLES::Resolver kMockResolverGLES
 

Typedef Documentation

◆ AiksCanvasTest

using impeller::testing::AiksCanvasTest = typedef ::testing::Test

Definition at line 16 of file canvas_unittests.cc.

◆ AiksTest

Definition at line 17 of file aiks_unittests.h.

◆ BlitPassTest

Definition at line 15 of file blit_pass_unittests.cc.

◆ ComputeSubgroupTest

Definition at line 39 of file compute_subgroup_unittests.cc.

◆ ComputeTest

Definition at line 21 of file compute_unittests.cc.

◆ DeviceBufferTest

Definition at line 12 of file device_buffer_unittests.cc.

◆ DisplayListTest

Definition at line 46 of file dl_unittests.cc.

◆ DriverInfoVKTest

Definition at line 11 of file driver_info_vk_unittests.cc.

◆ EntityPassTargetTest

Definition at line 16 of file entity_pass_target_unittests.cc.

◆ EntityTest

Definition at line 20 of file checkerboard_contents_unittests.cc.

◆ HostBufferTest

Definition at line 12 of file host_buffer_unittests.cc.

◆ RendererTest

Definition at line 14 of file render_pass_cache_unittests.cc.

◆ RenderTargetCacheTest

Definition at line 19 of file render_target_cache_unittests.cc.

◆ RuntimeStageTest

Definition at line 25 of file runtime_stage_unittests.cc.

◆ TypographerTest

Definition at line 25 of file typographer_unittests.cc.

Function Documentation

◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [1/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST ( Conical  )

◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [2/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST ( Linear  )

◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [3/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST ( Radial  )

◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [4/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST ( Sweep  )

◆ BlendModeTest()

static Picture impeller::testing::BlendModeTest ( Vector2  content_scale,
BlendMode  blend_mode,
const std::shared_ptr< Image > &  src_image,
const std::shared_ptr< Image > &  dst_image,
Scalar  src_alpha 
)
static
  1. Save layer blending (top squares).
  1. CPU blend modes (bottom squares).
  1. Image blending (bottom images).

Compare these results with the images in the Flutter blend mode documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html

Definition at line 368 of file aiks_blend_unittests.cc.

372 {
373 if (AiksTest::ImGuiBegin("Controls", nullptr,
374 ImGuiWindowFlags_AlwaysAutoResize)) {
375 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
376 ImGui::End();
377 }
378
379 Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
380 auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
381 Color::LimeGreen().WithAlpha(0.75),
382 Color::Black().WithAlpha(0.75)});
383
384 Canvas canvas;
385 canvas.DrawPaint({.color = Color::Black()});
386 // TODO(bdero): Why does this cause the left image to double scale on high DPI
387 // displays.
388 // canvas.Scale(content_scale);
389
390 //----------------------------------------------------------------------------
391 /// 1. Save layer blending (top squares).
392 ///
393
394 canvas.Save();
395 for (const auto& color : source_colors) {
396 canvas.Save();
397 {
398 canvas.ClipRect(Rect::MakeXYWH(25, 25, 100, 100));
399 // Perform the blend in a SaveLayer so that the initial backdrop color is
400 // fully transparent black. SourceOver blend the result onto the parent
401 // pass.
402 canvas.SaveLayer({});
403 {
404 canvas.DrawPaint({.color = destination_color});
405 // Draw the source color in an offscreen pass and blend it to the parent
406 // pass.
407 canvas.SaveLayer({.blend_mode = blend_mode});
408 { //
409 canvas.DrawRect(Rect::MakeXYWH(25, 25, 100, 100), {.color = color});
410 }
411 canvas.Restore();
412 }
413 canvas.Restore();
414 }
415 canvas.Restore();
416 canvas.Translate(Vector2(100, 0));
417 }
418 canvas.RestoreToCount(0);
419
420 //----------------------------------------------------------------------------
421 /// 2. CPU blend modes (bottom squares).
422 ///
423
424 canvas.Save();
425 canvas.Translate({0, 100});
426 // Perform the blend in a SaveLayer so that the initial backdrop color is
427 // fully transparent black. SourceOver blend the result onto the parent pass.
428 canvas.SaveLayer({});
429 for (const auto& color : source_colors) {
430 // Simply write the CPU blended color to the pass.
431 canvas.DrawRect(Rect::MakeXYWH(25, 25, 100, 100),
432 {.color = destination_color.Blend(color, blend_mode),
433 .blend_mode = BlendMode::kSourceOver});
434 canvas.Translate(Vector2(100, 0));
435 }
436 canvas.Restore();
437 canvas.Restore();
438
439 //----------------------------------------------------------------------------
440 /// 3. Image blending (bottom images).
441 ///
442 /// Compare these results with the images in the Flutter blend mode
443 /// documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html
444 ///
445
446 canvas.Translate({0, 250});
447
448 // Draw grid behind the images.
449 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 400),
450 {.color = Color::MakeRGBA8(41, 41, 41, 255)});
451 Paint square_paint = {.color = Color::MakeRGBA8(15, 15, 15, 255)};
452 for (int y = 0; y < 400 / 8; y++) {
453 for (int x = 0; x < 800 / 16; x++) {
454 canvas.DrawRect(Rect::MakeXYWH(x * 16 + (y % 2) * 8, y * 8, 8, 8),
455 square_paint);
456 }
457 }
458
459 // Uploaded image source (left image).
460 canvas.Save();
461 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
462 {
463 canvas.DrawImage(dst_image, {0, 0},
464 {
465 .blend_mode = BlendMode::kSourceOver,
466 });
467 canvas.DrawImage(src_image, {0, 0},
468 {
469 .color = Color::White().WithAlpha(src_alpha),
470 .blend_mode = blend_mode,
471 });
472 }
473 canvas.Restore();
474 canvas.Restore();
475
476 // Rendered image source (right image).
477 canvas.Save();
478 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
479 {
480 canvas.DrawImage(dst_image, {400, 0},
481 {.blend_mode = BlendMode::kSourceOver});
482 canvas.SaveLayer({.color = Color::White().WithAlpha(src_alpha),
483 .blend_mode = blend_mode});
484 {
485 canvas.DrawImage(src_image, {400, 0},
486 {.blend_mode = BlendMode::kSourceOver});
487 }
488 canvas.Restore();
489 }
490 canvas.Restore();
491 canvas.Restore();
492
493 return canvas.EndRecordingAsPicture();
494}
SkColor4f color
double y
double x
Point Vector2
Definition point.h:320
constexpr Color WithAlpha(Scalar new_alpha) const
Definition color.h:270
Color Blend(Color source, BlendMode blend_mode) const
Blends an unpremultiplied destination color into a given unpremultiplied source color to form a new u...
Definition color.cc:234

◆ CanRenderConicalGradientWithDithering()

static void impeller::testing::CanRenderConicalGradientWithDithering ( AiksTest aiks_test,
bool  use_dithering 
)
static

Definition at line 166 of file aiks_gradient_unittests.cc.

167 {
168 Canvas canvas;
169 canvas.Scale(aiks_test->GetContentScale());
170 Paint paint;
171 canvas.Translate({100.0, 100.0, 0});
172
173 // #FFF -> #000
174 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
175 Color{0.0, 0.0, 0.0, 1.0}};
176 std::vector<Scalar> stops = {0.0, 1.0};
177
178 paint.color_source = ColorSource::MakeConicalGradient(
179 {100, 100}, 100, std::move(colors), std::move(stops), {0, 1}, 0,
180 Entity::TileMode::kMirror, {});
181 paint.dither = use_dithering;
182
183 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
184 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
185}
bool OpenPlaygroundHere(Picture picture)
void Scale(const Vector2 &scale)
Definition canvas.cc:313
Picture EndRecordingAsPicture()
Definition canvas.cc:802
void DrawRect(const Rect &rect, const Paint &paint)
Definition canvas.cc:493
void Translate(const Vector3 &offset)
Definition canvas.cc:309
Point GetContentScale() const
const Paint & paint

◆ CanRenderLinearGradientWithDithering()

static void impeller::testing::CanRenderLinearGradientWithDithering ( AiksTest aiks_test,
bool  use_dithering 
)
static

Definition at line 82 of file aiks_gradient_unittests.cc.

83 {
84 Canvas canvas;
86 canvas.Translate({100.0, 100.0, 0});
87
88 // 0xffcccccc --> 0xff333333, taken from
89 // https://github.com/flutter/flutter/issues/118073#issue-1521699748
90 std::vector<Color> colors = {Color{0.8, 0.8, 0.8, 1.0},
91 Color{0.2, 0.2, 0.2, 1.0}};
92 std::vector<Scalar> stops = {0.0, 1.0};
93
94 paint.color_source = ColorSource::MakeLinearGradient(
95 {0, 0}, {800, 500}, std::move(colors), std::move(stops),
96 Entity::TileMode::kClamp, {});
97 paint.dither = use_dithering;
98 canvas.DrawRect(Rect::MakeXYWH(0, 0, 800, 500), paint);
99 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
100}

◆ CanRenderRadialGradientWithDithering()

static void impeller::testing::CanRenderRadialGradientWithDithering ( AiksTest aiks_test,
bool  use_dithering 
)
static

Definition at line 110 of file aiks_gradient_unittests.cc.

111 {
112 Canvas canvas;
113 Paint paint;
114 canvas.Translate({100.0, 100.0, 0});
115
116 // #FFF -> #000
117 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
118 Color{0.0, 0.0, 0.0, 1.0}};
119 std::vector<Scalar> stops = {0.0, 1.0};
120
121 paint.color_source = ColorSource::MakeRadialGradient(
122 {600, 600}, 600, std::move(colors), std::move(stops),
123 Entity::TileMode::kClamp, {});
124 paint.dither = use_dithering;
125 canvas.DrawRect(Rect::MakeXYWH(0, 0, 1200, 1200), paint);
126 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
127}

◆ CanRenderSweepGradientWithDithering()

static void impeller::testing::CanRenderSweepGradientWithDithering ( AiksTest aiks_test,
bool  use_dithering 
)
static

Definition at line 137 of file aiks_gradient_unittests.cc.

138 {
139 Canvas canvas;
140 canvas.Scale(aiks_test->GetContentScale());
141 Paint paint;
142 canvas.Translate({100.0, 100.0, 0});
143
144 // #FFF -> #000
145 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
146 Color{0.0, 0.0, 0.0, 1.0}};
147 std::vector<Scalar> stops = {0.0, 1.0};
148
149 paint.color_source = ColorSource::MakeSweepGradient(
150 {100, 100}, Degrees(45), Degrees(135), std::move(colors),
151 std::move(stops), Entity::TileMode::kMirror, {});
152 paint.dither = use_dithering;
153
154 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
155 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
156}

◆ CAPABILITY_TEST() [1/10]

impeller::testing::CAPABILITY_TEST ( SupportsBufferToTextureBlits  ,
false   
)

◆ CAPABILITY_TEST() [2/10]

impeller::testing::CAPABILITY_TEST ( SupportsCompute  ,
false   
)

◆ CAPABILITY_TEST() [3/10]

impeller::testing::CAPABILITY_TEST ( SupportsComputeSubgroups  ,
false   
)

◆ CAPABILITY_TEST() [4/10]

impeller::testing::CAPABILITY_TEST ( SupportsDecalSamplerAddressMode  ,
false   
)

◆ CAPABILITY_TEST() [5/10]

impeller::testing::CAPABILITY_TEST ( SupportsDeviceTransientTextures  ,
false   
)

◆ CAPABILITY_TEST() [6/10]

impeller::testing::CAPABILITY_TEST ( SupportsFramebufferFetch  ,
false   
)

◆ CAPABILITY_TEST() [7/10]

impeller::testing::CAPABILITY_TEST ( SupportsOffscreenMSAA  ,
false   
)

◆ CAPABILITY_TEST() [8/10]

impeller::testing::CAPABILITY_TEST ( SupportsReadFromResolve  ,
false   
)

◆ CAPABILITY_TEST() [9/10]

impeller::testing::CAPABILITY_TEST ( SupportsSSBO  ,
false   
)

◆ CAPABILITY_TEST() [10/10]

impeller::testing::CAPABILITY_TEST ( SupportsTextureToTextureBlits  ,
false   
)

◆ CompareFunctionUI()

static const CompareFunctionUIData & impeller::testing::CompareFunctionUI ( )
static

Definition at line 1108 of file renderer_unittests.cc.

1108 {
1109 static CompareFunctionUIData data;
1110 return data;
1111}

◆ CreateDefaultPipeline()

template<class VertexShader , class FragmentShader >
std::shared_ptr< Pipeline< PipelineDescriptor > > impeller::testing::CreateDefaultPipeline ( const std::shared_ptr< Context > &  context)

Definition at line 1300 of file renderer_unittests.cc.

1301 {
1302 using TexturePipelineBuilder = PipelineBuilder<VertexShader, FragmentShader>;
1303 auto pipeline_desc =
1304 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1305 if (!pipeline_desc.has_value()) {
1306 return nullptr;
1307 }
1308 pipeline_desc->SetSampleCount(SampleCount::kCount4);
1309 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1310 auto pipeline =
1311 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1312 if (!pipeline || !pipeline->IsValid()) {
1313 return nullptr;
1314 }
1315 return pipeline;
1316}
An optional (but highly recommended) utility for creating pipelines from reflected shader information...

◆ CreateGlyphAtlas()

static std::shared_ptr< GlyphAtlas > impeller::testing::CreateGlyphAtlas ( Context context,
const TypographerContext typographer_context,
GlyphAtlas::Type  type,
Scalar  scale,
const std::shared_ptr< GlyphAtlasContext > &  atlas_context,
const TextFrame frame 
)
static

Definition at line 28 of file typographer_unittests.cc.

34 {
35 FontGlyphMap font_glyph_map;
36 frame.CollectUniqueFontGlyphPairs(font_glyph_map, scale);
37 return typographer_context->CreateGlyphAtlas(context, type, atlas_context,
38 font_glyph_map);
39}
virtual std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const FontGlyphMap &font_glyph_map) const =0
double frame
Definition examples.cpp:31
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
const Scalar scale

◆ CreateMappingFromString()

static std::shared_ptr< fml::Mapping > impeller::testing::CreateMappingFromString ( std::string  p_string)
static

Definition at line 20 of file shader_archive_unittests.cc.

21 {
22 auto string = std::make_shared<std::string>(std::move(p_string));
23 return std::make_shared<fml::NonOwnedMapping>(
24 reinterpret_cast<const uint8_t*>(string->data()), string->size(),
25 [string](auto, auto) {});
26}

◆ CreatePassWithRectPath()

auto impeller::testing::CreatePassWithRectPath ( Rect  rect,
std::optional< Rect bounds_hint,
ContentBoundsPromise  bounds_promise = ContentBoundsPromise::kUnknown,
bool  collapse = false 
)

Definition at line 109 of file entity_unittests.cc.

113 {
114 auto subpass = std::make_unique<EntityPass>();
115 Entity entity;
116 entity.SetContents(SolidColorContents::Make(
117 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
118 subpass->AddEntity(std::move(entity));
119 subpass->SetDelegate(std::make_unique<TestPassDelegate>(collapse));
120 subpass->SetBoundsLimit(bounds_hint, bounds_promise);
121 return subpass;
122}
void SetContents(std::shared_ptr< Contents > contents)
Definition entity.cc:90
PathBuilder & AddRect(Rect rect)

◆ CreateStringFromMapping()

const std::string impeller::testing::CreateStringFromMapping ( const fml::Mapping mapping)

Definition at line 28 of file shader_archive_unittests.cc.

28 {
29 return std::string{reinterpret_cast<const char*>(mapping.GetMapping()),
30 mapping.GetSize()};
31}
virtual const uint8_t * GetMapping() const =0
virtual size_t GetSize() const =0

◆ CreateSurface()

vk::UniqueSurfaceKHR impeller::testing::CreateSurface ( const ContextVK context)

Definition at line 16 of file swapchain_unittests.cc.

16 {
17#if FML_OS_DARWIN
18 impeller::vk::MetalSurfaceCreateInfoEXT createInfo = {};
19 auto [result, surface] =
20 context.GetInstance().createMetalSurfaceEXTUnique(createInfo);
21 FML_DCHECK(result == vk::Result::eSuccess);
22 return std::move(surface);
23#else
24 return {};
25#endif // FML_OS_DARWIN
26}
vk::Instance GetInstance() const
VkSurfaceKHR surface
Definition main.cc:49
GAsyncResult * result
#define FML_DCHECK(condition)
Definition logging.h:103

◆ CreateTestYUVTextures()

static std::vector< std::shared_ptr< Texture > > impeller::testing::CreateTestYUVTextures ( Context context,
YUVColorSpace  yuv_color_space 
)
static

Definition at line 2047 of file entity_unittests.cc.

2049 {
2050 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
2051 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
2052 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
2053 Vector3 white = {1.0, 1.0, 1.0};
2054 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
2055 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
2056 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
2057 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
2058 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
2059 std::vector<uint8_t> y_data;
2060 std::vector<uint8_t> uv_data;
2061 for (int i = 0; i < 4; i++) {
2062 auto yuv = yuvs[i];
2063 uint8_t y = std::round(yuv.x * 255.0);
2064 uint8_t u = std::round(yuv.y * 255.0);
2065 uint8_t v = std::round(yuv.z * 255.0);
2066 for (int j = 0; j < 16; j++) {
2067 y_data.push_back(y);
2068 }
2069 for (int j = 0; j < 8; j++) {
2070 uv_data.push_back(j % 2 == 0 ? u : v);
2071 }
2072 }
2073 impeller::TextureDescriptor y_texture_descriptor;
2075 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
2076 y_texture_descriptor.size = {8, 8};
2077 auto y_texture =
2078 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
2079 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
2080 if (!y_texture->SetContents(y_mapping)) {
2081 FML_DLOG(ERROR) << "Could not copy contents into Y texture.";
2082 }
2083
2084 impeller::TextureDescriptor uv_texture_descriptor;
2085 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
2086 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
2087 uv_texture_descriptor.size = {4, 4};
2088 auto uv_texture =
2089 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
2090 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
2091 if (!uv_texture->SetContents(uv_mapping)) {
2092 FML_DLOG(ERROR) << "Could not copy contents into UV texture.";
2093 }
2094
2095 return {y_texture, uv_texture};
2096}
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
#define FML_DLOG(severity)
Definition logging.h:102
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define ERROR(message)

◆ doNothing()

void impeller::testing::doNothing ( )

Definition at line 42 of file mock_gles.cc.

42{}

◆ flip_lr()

template<typename R >
static constexpr R impeller::testing::flip_lr ( R  rect)
inlinestaticconstexpr

Definition at line 1279 of file rect_unittests.cc.

1279 {
1280 return R::MakeLTRB(rect.GetRight(), rect.GetTop(), //
1281 rect.GetLeft(), rect.GetBottom());
1282}

◆ flip_lrtb()

template<typename R >
static constexpr R impeller::testing::flip_lrtb ( R  rect)
inlinestaticconstexpr

Definition at line 1291 of file rect_unittests.cc.

1291 {
1292 return flip_lr(flip_tb(rect));
1293}
static constexpr R flip_tb(R rect)
static constexpr R flip_lr(R rect)

◆ flip_tb()

template<typename R >
static constexpr R impeller::testing::flip_tb ( R  rect)
inlinestaticconstexpr

Definition at line 1285 of file rect_unittests.cc.

1285 {
1286 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(), //
1287 rect.GetRight(), rect.GetTop());
1288}

◆ GetBlendModeSelection()

static BlendModeSelection impeller::testing::GetBlendModeSelection ( )
static

Definition at line 188 of file aiks_blend_unittests.cc.

188 {
189 std::vector<const char*> blend_mode_names;
190 std::vector<BlendMode> blend_mode_values;
191 {
192 const std::vector<std::tuple<const char*, BlendMode>> blends = {
194 assert(blends.size() ==
195 static_cast<size_t>(Entity::kLastAdvancedBlendMode) + 1);
196 for (const auto& [name, mode] : blends) {
197 blend_mode_names.push_back(name);
198 blend_mode_values.push_back(mode);
199 }
200 }
201
202 return {blend_mode_names, blend_mode_values};
203}
#define BLEND_MODE_TUPLE(blend_mode)
#define IMPELLER_FOR_EACH_BLEND_MODE(V)
Definition color.h:19
const char * name
Definition fuchsia.cc:50

◆ GetCoverageOfFirstEntity()

template<typename Contents >
static std::optional< Rect > impeller::testing::GetCoverageOfFirstEntity ( const Picture picture)
static

Definition at line 1752 of file dl_unittests.cc.

1752 {
1753 std::optional<Rect> coverage;
1754 picture.pass->IterateAllEntities([&coverage](Entity& entity) {
1755 if (std::static_pointer_cast<Contents>(entity.GetContents())) {
1756 auto contents = std::static_pointer_cast<Contents>(entity.GetContents());
1757 Entity entity;
1758 coverage = contents->GetCoverage(entity);
1759 return false;
1760 }
1761 return true;
1762 });
1763 return coverage;
1764}
const std::shared_ptr< Contents > & GetContents() const
Definition entity.cc:94

◆ GetMockVulkanFunctions()

std::shared_ptr< std::vector< std::string > > impeller::testing::GetMockVulkanFunctions ( VkDevice  device)

Definition at line 926 of file mock_vulkan.cc.

927 {
928 MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
929 return mock_device->GetCalledFunctions();
930}
VkDevice device
Definition main.cc:53

◆ INSTANTIATE_COMPUTE_SUITE()

impeller::testing::INSTANTIATE_COMPUTE_SUITE ( ComputeSubgroupTest  )

◆ INSTANTIATE_PLAYGROUND_SUITE() [1/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE ( AiksTest  )

◆ INSTANTIATE_PLAYGROUND_SUITE() [2/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE ( BlitPassTest  )

◆ INSTANTIATE_PLAYGROUND_SUITE() [3/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE ( DisplayListTest  )

◆ INSTANTIATE_PLAYGROUND_SUITE() [4/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE ( GaussianBlurFilterContentsTest  )

◆ INSTANTIATE_PLAYGROUND_SUITE() [5/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE ( HostBufferTest  )

◆ INSTANTIATE_PLAYGROUND_SUITE() [6/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE ( RendererDartTest  )

◆ INSTANTIATE_PLAYGROUND_SUITE() [7/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE ( RuntimeStageTest  )

◆ INSTANTIATE_VULKAN_PLAYGROUND_SUITE()

impeller::testing::INSTANTIATE_VULKAN_PLAYGROUND_SUITE ( DriverInfoVKTest  )

◆ InstantiateTestShaderLibrary()

static void impeller::testing::InstantiateTestShaderLibrary ( Context::BackendType  backend_type)
static

Definition at line 34 of file renderer_dart_unittests.cc.

34 {
35 auto fixture =
36 flutter::testing::OpenFixtureAsMapping("playground.shaderbundle");
38 backend_type, std::move(fixture));
40}
static void SetOverride(fml::RefPtr< ShaderLibrary > override_shader_library)
Sets a return override for MakeFromAsset for testing purposes.
static fml::RefPtr< ShaderLibrary > MakeFromFlatbuffer(impeller::Context::BackendType backend_type, std::shared_ptr< fml::Mapping > payload)
std::unique_ptr< fml::Mapping > OpenFixtureAsMapping(const std::string &fixture_name)
Opens a fixture of the given file name and returns a mapping to its contents.
Definition testing.cc:59

◆ MaskBlurVariantTest()

static Picture impeller::testing::MaskBlurVariantTest ( const AiksTest test_context,
const MaskBlurTestConfig config 
)
static

Definition at line 294 of file aiks_blur_unittests.cc.

295 {
296 Canvas canvas;
297 canvas.Scale(test_context.GetContentScale());
298 canvas.Scale(Vector2{0.8f, 0.8f});
299 Paint paint;
300 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
301 .style = FilterContents::BlurStyle::kNormal,
302 .sigma = Sigma{1},
303 };
304
305 canvas.DrawPaint({.color = Color::AntiqueWhite()});
306
307 paint.mask_blur_descriptor->style = config.style;
308 paint.mask_blur_descriptor->sigma = Sigma{config.sigma};
309 paint.image_filter = config.image_filter;
310 paint.invert_colors = config.invert_colors;
311 paint.blend_mode = config.blend_mode;
312
313 const Scalar x = 50;
314 const Scalar radius = 20.0f;
315 const Scalar y_spacing = 100.0f;
316
317 Scalar y = 50;
318 paint.color = Color::Crimson().WithAlpha(config.alpha);
319 canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
320 radius, 60.0f - radius),
321 paint);
322
323 y += y_spacing;
324 paint.color = Color::Blue().WithAlpha(config.alpha);
325 canvas.DrawCircle({x + 25, y + 25}, radius, paint);
326
327 y += y_spacing;
328 paint.color = Color::Green().WithAlpha(config.alpha);
329 canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
330 radius, 60.0f - radius),
331 paint);
332
333 y += y_spacing;
334 paint.color = Color::Purple().WithAlpha(config.alpha);
335 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
336 {radius, radius}, //
337 paint);
338
339 y += y_spacing;
340 paint.color = Color::Orange().WithAlpha(config.alpha);
341 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
342 {radius, 5.0f}, paint);
343
344 y += y_spacing;
345 paint.color = Color::Maroon().WithAlpha(config.alpha);
346 canvas.DrawPath(PathBuilder{}
347 .MoveTo({x + 0, y + 60})
348 .LineTo({x + 30, y + 0})
349 .LineTo({x + 60, y + 60})
350 .Close()
351 .TakePath(),
352 paint);
353
354 y += y_spacing;
355 paint.color = Color::Maroon().WithAlpha(config.alpha);
356 canvas.DrawPath(PathBuilder{}
357 .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50),
358 Radians{kPi / 2}, Radians{kPi})
359 .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50),
360 Radians{kPi / 2}, Radians{kPi})
361 .Close()
362 .TakePath(),
363 paint);
364
365 return canvas.EndRecordingAsPicture();
366}
void DrawOval(const Rect &rect, const Paint &paint)
Definition canvas.cc:512
void DrawPaint(const Paint &paint)
Definition canvas.cc:350
void DrawPath(const Path &path, const Paint &paint)
Definition canvas.cc:341
void DrawRRect(const Rect &rect, const Size &corner_radii, const Paint &paint)
Definition canvas.cc:538
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition canvas.cc:564
constexpr float kPi
Definition math.h:27
float Scalar
Definition scalar.h:18
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
void Close(PathBuilder *builder)
FilterContents::BlurStyle style
Definition paint.h:40
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition sigma.h:32
std::shared_ptr< ImageFilter > image_filter

◆ mockBeginQueryEXT()

void impeller::testing::mockBeginQueryEXT ( GLenum  target,
GLuint  id 
)

Definition at line 129 of file mock_gles.cc.

129 {
130 RecordGLCall("glBeginQueryEXT");
131}
void RecordGLCall(const char *name)
Definition mock_gles.cc:29

◆ mockDeleteQueriesEXT()

void impeller::testing::mockDeleteQueriesEXT ( GLsizei  size,
const GLuint *  queries 
)

Definition at line 159 of file mock_gles.cc.

159 {
160 RecordGLCall("glDeleteQueriesEXT");
161}

◆ mockEndQueryEXT()

void impeller::testing::mockEndQueryEXT ( GLuint  id)

Definition at line 136 of file mock_gles.cc.

136 {
137 RecordGLCall("glEndQueryEXT");
138}

◆ mockGenQueriesEXT()

void impeller::testing::mockGenQueriesEXT ( GLsizei  n,
GLuint *  ids 
)

Definition at line 119 of file mock_gles.cc.

119 {
120 RecordGLCall("glGenQueriesEXT");
121 for (auto i = 0; i < n; i++) {
122 ids[i] = i + 1;
123 }
124}

◆ mockGetError()

GLenum impeller::testing::mockGetError ( )

Definition at line 95 of file mock_gles.cc.

95 {
96 return GL_NO_ERROR;
97}

◆ mockGetIntegerv()

void impeller::testing::mockGetIntegerv ( GLenum  name,
int value 
)

Definition at line 78 of file mock_gles.cc.

78 {
79 switch (name) {
80 case GL_NUM_EXTENSIONS: {
81 *value = g_extensions.size();
82 } break;
83 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
84 *value = 8;
85 break;
86 default:
87 *value = 0;
88 break;
89 }
90}
uint8_t value
static std::vector< const unsigned char * > g_extensions
Definition mock_gles.cc:24

◆ mockGetQueryObjectui64vEXT()

void impeller::testing::mockGetQueryObjectui64vEXT ( GLuint  id,
GLenum  target,
GLuint64 *  result 
)

Definition at line 151 of file mock_gles.cc.

151 {
152 RecordGLCall("glGetQueryObjectui64vEXT");
153 *result = 1000u;
154}

◆ mockGetQueryObjectuivEXT()

void impeller::testing::mockGetQueryObjectuivEXT ( GLuint  id,
GLenum  target,
GLuint *  result 
)

Definition at line 143 of file mock_gles.cc.

143 {
144 RecordGLCall("glGetQueryObjectuivEXT");
145 *result = GL_TRUE;
146}

◆ mockGetString()

const unsigned char * impeller::testing::mockGetString ( GLenum  name)

Definition at line 50 of file mock_gles.cc.

50 {
51 switch (name) {
52 case GL_VENDOR:
53 return kMockVendor;
54 case GL_VERSION:
55 return g_version;
56 case GL_SHADING_LANGUAGE_VERSION:
58 default:
59 return (unsigned char*)"";
60 }
61}
const auto kMockShadingLanguageVersion
Definition mock_gles.cc:45
auto const kMockVendor
Definition mock_gles.cc:44
static const unsigned char * g_version
Definition mock_gles.cc:26

◆ mockGetStringi()

const unsigned char * impeller::testing::mockGetStringi ( GLenum  name,
GLuint  index 
)

Definition at line 66 of file mock_gles.cc.

66 {
67 switch (name) {
68 case GL_EXTENSIONS:
69 return g_extensions[index];
70 default:
71 return (unsigned char*)"";
72 }
73}

◆ mockPopDebugGroupKHR()

void impeller::testing::mockPopDebugGroupKHR ( )

Definition at line 102 of file mock_gles.cc.

102 {
103 RecordGLCall("PopDebugGroupKHR");
104}

◆ mockPushDebugGroupKHR()

void impeller::testing::mockPushDebugGroupKHR ( GLenum  source,
GLuint  id,
GLsizei  length,
const GLchar *  message 
)

Definition at line 109 of file mock_gles.cc.

112 {
113 RecordGLCall("PushDebugGroupKHR");
114}

◆ RecordGLCall()

void impeller::testing::RecordGLCall ( const char *  name)

Definition at line 29 of file mock_gles.cc.

29 {
30 if (auto mock_gles = g_mock_gles.lock()) {
31 mock_gles->RecordCall(name);
32 }
33}
static std::weak_ptr< MockGLES > g_mock_gles
Definition mock_gles.cc:20

◆ RenderTextInCanvasSkia()

bool impeller::testing::RenderTextInCanvasSkia ( const std::shared_ptr< Context > &  context,
Canvas canvas,
const std::string &  text,
const std::string_view &  font_fixture,
TextRenderOptions  options = {} 
)

Definition at line 668 of file aiks_unittests.cc.

672 {}) {
673 // Draw the baseline.
674 canvas.DrawRect(
675 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
676 Paint{.color = Color::Aqua().WithAlpha(0.25)});
677
678 // Mark the point at which the text is drawn.
679 canvas.DrawCircle(options.position, 5.0,
680 Paint{.color = Color::Red().WithAlpha(0.25)});
681
682 // Construct the text blob.
683 auto c_font_fixture = std::string(font_fixture);
684 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
685 if (!mapping) {
686 return false;
687 }
689 SkFont sk_font(font_mgr->makeFromData(mapping), options.font_size);
690 auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
691 if (!blob) {
692 return false;
693 }
694
695 // Create the Impeller text frame and draw it at the designated baseline.
697
698 Paint text_paint;
699 text_paint.color = options.color;
700 text_paint.mask_blur_descriptor = options.mask_blur_descriptor;
701 canvas.DrawTextFrame(frame, options.position, text_paint);
702 return true;
703}
const char * options
static sk_sp< SkTextBlob > MakeFromString(const char *string, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition SkTextBlob.h:115
virtual void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition canvas.cc:875
std::u16string text
sk_sp< SkData > OpenFixtureAsSkData(const std::string &fixture_name)
Opens a fixture of the given file name and returns a Skia SkData holding its contents.
Definition testing.cc:64
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
sk_sp< SkFontMgr > GetDefaultFontManager(uint32_t font_initialization_data)
Definition platform.cc:17
Color color
Definition paint.h:55

◆ RenderTextInCanvasSTB()

bool impeller::testing::RenderTextInCanvasSTB ( const std::shared_ptr< Context > &  context,
Canvas canvas,
const std::string &  text,
const std::string &  font_fixture,
TextRenderOptions  options = {} 
)

Definition at line 705 of file aiks_unittests.cc.

709 {}) {
710 // Draw the baseline.
711 canvas.DrawRect(
712 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
713 Paint{.color = Color::Aqua().WithAlpha(0.25)});
714
715 // Mark the point at which the text is drawn.
716 canvas.DrawCircle(options.position, 5.0,
717 Paint{.color = Color::Red().WithAlpha(0.25)});
718
719 // Construct the text blob.
720 auto mapping = flutter::testing::OpenFixtureAsMapping(font_fixture.c_str());
721 if (!mapping) {
722 return false;
723 }
724 auto typeface_stb = std::make_shared<TypefaceSTB>(std::move(mapping));
725
726 auto frame = MakeTextFrameSTB(
727 typeface_stb, Font::Metrics{.point_size = options.font_size}, text);
728
729 Paint text_paint;
730 text_paint.color = options.color;
731 canvas.DrawTextFrame(frame, options.position, text_paint);
732 return true;
733}
std::shared_ptr< TextFrame > MakeTextFrameSTB(const std::shared_ptr< TypefaceSTB > &typeface_stb, Font::Metrics metrics, const std::string &text)

◆ RGBToYUV()

static Vector3 impeller::testing::RGBToYUV ( Vector3  rgb,
YUVColorSpace  yuv_color_space 
)
static

Definition at line 2030 of file entity_unittests.cc.

2030 {
2031 Vector3 yuv;
2032 switch (yuv_color_space) {
2033 case YUVColorSpace::kBT601FullRange:
2034 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
2035 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
2036 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
2037 break;
2038 case YUVColorSpace::kBT601LimitedRange:
2039 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
2040 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
2041 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
2042 break;
2043 }
2044 return yuv;
2045}

◆ SetSwapchainImageSize()

void impeller::testing::SetSwapchainImageSize ( ISize  size)

Override the image size returned by all swapchain images.

Definition at line 932 of file mock_vulkan.cc.

932 {
933 currentImageSize = size;
934}

◆ swap_nan() [1/2]

static constexpr Point impeller::testing::swap_nan ( const Point point,
int  index 
)
inlinestaticconstexpr

Definition at line 1305 of file rect_unittests.cc.

1305 {
1306 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1307 FML_DCHECK(index >= 0 && index <= 3);
1308 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.x;
1309 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.y;
1310 return Point(x, y);
1311}

◆ swap_nan() [2/2]

static constexpr Rect impeller::testing::swap_nan ( const Rect rect,
int  index 
)
inlinestaticconstexpr

Definition at line 1295 of file rect_unittests.cc.

1295 {
1296 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1297 FML_DCHECK(index >= 0 && index <= 15);
1298 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.GetLeft();
1299 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.GetTop();
1300 Scalar r = ((index & (1 << 2)) != 0) ? nan : rect.GetRight();
1301 Scalar b = ((index & (1 << 3)) != 0) ? nan : rect.GetBottom();
1302 return Rect::MakeLTRB(l, t, r, b);
1303}
static bool b

◆ TEST() [1/399]

impeller::testing::TEST ( AiksCanvasTest  ,
DisableLocalBoundsRectForFilteredSaveLayers   
)

Definition at line 340 of file canvas_unittests.cc.

340 {
341 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
342
343 Canvas canvas(initial_cull);
344 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
345
346 canvas.Save();
347 canvas.SaveLayer(
348 Paint{.image_filter = ImageFilter::MakeBlur(
349 Sigma(10), Sigma(10), FilterContents::BlurStyle::kNormal,
350 Entity::TileMode::kDecal)});
351 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
352
353 canvas.Restore();
354 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
355}
std::shared_ptr< ImageFilter > image_filter
Definition paint.h:67

◆ TEST() [2/399]

impeller::testing::TEST ( AiksCanvasTest  ,
EmptyCullRect   
)

Definition at line 18 of file canvas_unittests.cc.

18 {
19 Canvas canvas;
20
21 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
22}
const std::optional< Rect > GetCurrentLocalCullingBounds() const
Definition canvas.cc:300

◆ TEST() [3/399]

impeller::testing::TEST ( AiksCanvasTest  ,
InitialCullRect   
)

Definition at line 24 of file canvas_unittests.cc.

24 {
25 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
26
27 Canvas canvas(initial_cull);
28
29 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
30 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), initial_cull);
31}

◆ TEST() [4/399]

impeller::testing::TEST ( AiksCanvasTest  ,
PathClipDiffAgainstEmptyCullRect   
)

Definition at line 277 of file canvas_unittests.cc.

277 {
278 PathBuilder builder;
279 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
280 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
281 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
282 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
283 Path path = builder.TakePath();
284
285 Canvas canvas;
286 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
287
288 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
289}
void ClipPath(const Path &path, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition canvas.cc:587
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition path.h:51

◆ TEST() [5/399]

impeller::testing::TEST ( AiksCanvasTest  ,
PathClipDiffAgainstFullyCoveredCullRect   
)

Definition at line 325 of file canvas_unittests.cc.

325 {
326 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
327 PathBuilder builder;
328 builder.AddRect(Rect::MakeXYWH(0, 0, 100, 100));
329 Path path = builder.TakePath();
330 // Diff clip of Paths is ignored due to complexity
331 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
332
333 Canvas canvas(initial_cull);
334 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
335
336 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
337 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
338}

◆ TEST() [6/399]

impeller::testing::TEST ( AiksCanvasTest  ,
PathClipDiffAgainstNonCoveredCullRect   
)

Definition at line 308 of file canvas_unittests.cc.

308 {
309 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
310 PathBuilder builder;
311 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
312 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
313 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
314 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
315 Path path = builder.TakePath();
316 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
317
318 Canvas canvas(initial_cull);
319 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
320
321 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
322 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
323}

◆ TEST() [7/399]

impeller::testing::TEST ( AiksCanvasTest  ,
PathClipIntersectAgainstCullRect   
)

Definition at line 291 of file canvas_unittests.cc.

291 {
292 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
293 PathBuilder builder;
294 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
295 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
296 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
297 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
298 Path path = builder.TakePath();
299 Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
300
301 Canvas canvas(initial_cull);
302 canvas.ClipPath(path, Entity::ClipOperation::kIntersect);
303
304 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
305 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
306}

◆ TEST() [8/399]

impeller::testing::TEST ( AiksCanvasTest  ,
PathClipIntersectAgainstEmptyCullRect   
)

Definition at line 261 of file canvas_unittests.cc.

261 {
262 PathBuilder builder;
263 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
264 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
265 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
266 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
267 Path path = builder.TakePath();
268 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
269
270 Canvas canvas;
271 canvas.ClipPath(path, Entity::ClipOperation::kIntersect);
272
273 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
274 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
275}

◆ TEST() [9/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffAboveCullRect   
)

Definition at line 98 of file canvas_unittests.cc.

98 {
99 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
100 Rect rect_clip = Rect::MakeXYWH(0, 0, 20, 4);
101 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
102
103 Canvas canvas(initial_cull);
104 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
105
106 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
107 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
108}

◆ TEST() [10/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffAgainstEmptyCullRect   
)

Definition at line 65 of file canvas_unittests.cc.

65 {
66 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
67
68 Canvas canvas;
69 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
70
71 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
72}
void ClipRect(const Rect &rect, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition canvas.cc:597

◆ TEST() [11/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffAgainstHCoveredCullRect   
)

Definition at line 158 of file canvas_unittests.cc.

158 {
159 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
160 Rect rect_clip = Rect::MakeXYWH(0, 5, 10, 10);
161 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 5);
162
163 Canvas canvas(initial_cull);
164 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
165
166 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
167 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
168}

◆ TEST() [12/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffAgainstNonCoveredCullRect   
)

Definition at line 86 of file canvas_unittests.cc.

86 {
87 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
88 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
89 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
90
91 Canvas canvas(initial_cull);
92 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
93
94 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
95 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
96}

◆ TEST() [13/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffAgainstVCoveredCullRect   
)

Definition at line 146 of file canvas_unittests.cc.

146 {
147 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
148 Rect rect_clip = Rect::MakeXYWH(5, 0, 10, 10);
149 Rect result_cull = Rect::MakeXYWH(0, 0, 5, 10);
150
151 Canvas canvas(initial_cull);
152 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
153
154 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
155 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
156}

◆ TEST() [14/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffBelowCullRect   
)

Definition at line 110 of file canvas_unittests.cc.

110 {
111 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
112 Rect rect_clip = Rect::MakeXYWH(0, 16, 20, 4);
113 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
114
115 Canvas canvas(initial_cull);
116 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
117
118 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
119 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
120}

◆ TEST() [15/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffLeftOfCullRect   
)

Definition at line 122 of file canvas_unittests.cc.

122 {
123 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
124 Rect rect_clip = Rect::MakeXYWH(0, 0, 4, 20);
125 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
126
127 Canvas canvas(initial_cull);
128 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
129
130 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
131 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
132}

◆ TEST() [16/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipDiffRightOfCullRect   
)

Definition at line 134 of file canvas_unittests.cc.

134 {
135 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
136 Rect rect_clip = Rect::MakeXYWH(16, 0, 4, 20);
137 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
138
139 Canvas canvas(initial_cull);
140 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
141
142 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
143 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
144}

◆ TEST() [17/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipIntersectAgainstCullRect   
)

Definition at line 74 of file canvas_unittests.cc.

74 {
75 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
76 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
77 Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
78
79 Canvas canvas(initial_cull);
80 canvas.ClipRect(rect_clip, Entity::ClipOperation::kIntersect);
81
82 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
83 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
84}

◆ TEST() [18/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RectClipIntersectAgainstEmptyCullRect   
)

Definition at line 55 of file canvas_unittests.cc.

55 {
56 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
57
58 Canvas canvas;
59 canvas.ClipRect(rect_clip, Entity::ClipOperation::kIntersect);
60
61 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
62 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
63}

◆ TEST() [19/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipDiffAgainstEmptyCullRect   
)

Definition at line 180 of file canvas_unittests.cc.

180 {
181 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
182
183 Canvas canvas;
184 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
185
186 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
187}
void ClipRRect(const Rect &rect, const Size &corner_radii, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition canvas.cc:638

◆ TEST() [20/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipDiffAgainstHFullyCoveredCullRect   
)

Definition at line 249 of file canvas_unittests.cc.

249 {
250 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
251 Rect rect_clip = Rect::MakeXYWH(-2, 5, 14, 10);
252 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 5);
253
254 Canvas canvas(initial_cull);
255 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
256
257 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
258 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
259}

◆ TEST() [21/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipDiffAgainstHPartiallyCoveredCullRect   
)

Definition at line 237 of file canvas_unittests.cc.

237 {
238 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
239 Rect rect_clip = Rect::MakeXYWH(0, 5, 10, 10);
240 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 6);
241
242 Canvas canvas(initial_cull);
243 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
244
245 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
246 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
247}

◆ TEST() [22/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipDiffAgainstNonCoveredCullRect   
)

Definition at line 201 of file canvas_unittests.cc.

201 {
202 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
203 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
204 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
205
206 Canvas canvas(initial_cull);
207 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
208
209 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
210 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
211}

◆ TEST() [23/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipDiffAgainstVFullyCoveredCullRect   
)

Definition at line 225 of file canvas_unittests.cc.

225 {
226 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
227 Rect rect_clip = Rect::MakeXYWH(5, -2, 10, 14);
228 Rect result_cull = Rect::MakeXYWH(0, 0, 5, 10);
229
230 Canvas canvas(initial_cull);
231 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
232
233 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
234 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
235}

◆ TEST() [24/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipDiffAgainstVPartiallyCoveredCullRect   
)

Definition at line 213 of file canvas_unittests.cc.

213 {
214 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
215 Rect rect_clip = Rect::MakeXYWH(5, 0, 10, 10);
216 Rect result_cull = Rect::MakeXYWH(0, 0, 6, 10);
217
218 Canvas canvas(initial_cull);
219 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
220
221 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
222 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
223}

◆ TEST() [25/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipIntersectAgainstCullRect   
)

Definition at line 189 of file canvas_unittests.cc.

189 {
190 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
191 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
192 Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
193
194 Canvas canvas(initial_cull);
195 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kIntersect);
196
197 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
198 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
199}

◆ TEST() [26/399]

impeller::testing::TEST ( AiksCanvasTest  ,
RRectClipIntersectAgainstEmptyCullRect   
)

Definition at line 170 of file canvas_unittests.cc.

170 {
171 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
172
173 Canvas canvas;
174 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kIntersect);
175
176 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
177 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
178}

◆ TEST() [27/399]

impeller::testing::TEST ( AiksCanvasTest  ,
ScaledCullRect   
)

Definition at line 44 of file canvas_unittests.cc.

44 {
45 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
46 Rect scaled_cull = Rect::MakeXYWH(10, 10, 20, 20);
47
48 Canvas canvas(initial_cull);
49 canvas.Scale(Vector2(0.5, 0.5));
50
51 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
52 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), scaled_cull);
53}

◆ TEST() [28/399]

impeller::testing::TEST ( AiksCanvasTest  ,
TranslatedCullRect   
)

Definition at line 33 of file canvas_unittests.cc.

33 {
34 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
35 Rect translated_cull = Rect::MakeXYWH(0, 0, 10, 10);
36
37 Canvas canvas(initial_cull);
38 canvas.Translate(Vector3(5, 5, 0));
39
40 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
41 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), translated_cull);
42}

◆ TEST() [29/399]

impeller::testing::TEST ( AllocatorTest  ,
TextureDescriptorCompatibility   
)

Definition at line 16 of file allocator_unittests.cc.

16 {
17 // Size.
18 {
19 TextureDescriptor desc_a = {.size = ISize(100, 100)};
20 TextureDescriptor desc_b = {.size = ISize(100, 100)};
21 TextureDescriptor desc_c = {.size = ISize(101, 100)};
22
23 ASSERT_EQ(desc_a, desc_b);
24 ASSERT_NE(desc_a, desc_c);
25 }
26 // Storage Mode.
27 {
28 TextureDescriptor desc_a = {.storage_mode = StorageMode::kDevicePrivate};
29 TextureDescriptor desc_b = {.storage_mode = StorageMode::kDevicePrivate};
30 TextureDescriptor desc_c = {.storage_mode = StorageMode::kHostVisible};
31
32 ASSERT_EQ(desc_a, desc_b);
33 ASSERT_NE(desc_a, desc_c);
34 }
35 // Format.
36 {
37 TextureDescriptor desc_a = {.format = PixelFormat::kR8G8B8A8UNormInt};
38 TextureDescriptor desc_b = {.format = PixelFormat::kR8G8B8A8UNormInt};
39 TextureDescriptor desc_c = {.format = PixelFormat::kB10G10R10A10XR};
40
41 ASSERT_EQ(desc_a, desc_b);
42 ASSERT_NE(desc_a, desc_c);
43 }
44 // Sample Count.
45 {
46 TextureDescriptor desc_a = {.sample_count = SampleCount::kCount4};
47 TextureDescriptor desc_b = {.sample_count = SampleCount::kCount4};
48 TextureDescriptor desc_c = {.sample_count = SampleCount::kCount1};
49
50 ASSERT_EQ(desc_a, desc_b);
51 ASSERT_NE(desc_a, desc_c);
52 }
53 // Sample Count.
54 {
55 TextureDescriptor desc_a = {.type = TextureType::kTexture2DMultisample};
56 TextureDescriptor desc_b = {.type = TextureType::kTexture2DMultisample};
57 TextureDescriptor desc_c = {.type = TextureType::kTexture2D};
58
59 ASSERT_EQ(desc_a, desc_b);
60 ASSERT_NE(desc_a, desc_c);
61 }
62 // Compression.
63 {
64 TextureDescriptor desc_a = {.compression_type = CompressionType::kLossless};
65 TextureDescriptor desc_b = {.compression_type = CompressionType::kLossless};
66 TextureDescriptor desc_c = {.compression_type = CompressionType::kLossy};
67
68 ASSERT_EQ(desc_a, desc_b);
69 ASSERT_NE(desc_a, desc_c);
70 }
71 // Mip Count.
72 {
73 TextureDescriptor desc_a = {.mip_count = 1};
74 TextureDescriptor desc_b = {.mip_count = 1};
75 TextureDescriptor desc_c = {.mip_count = 4};
76
77 ASSERT_EQ(desc_a, desc_b);
78 ASSERT_NE(desc_a, desc_c);
79 }
80}

◆ TEST() [30/399]

impeller::testing::TEST ( AllocatorVKTest  ,
MemoryTypeSelectionSingleHeap   
)

Definition at line 35 of file allocator_vk_unittests.cc.

35 {
36 vk::PhysicalDeviceMemoryProperties properties;
37 properties.memoryTypeCount = 1;
38 properties.memoryHeapCount = 1;
39 properties.memoryTypes[0].heapIndex = 0;
40 properties.memoryTypes[0].propertyFlags =
41 vk::MemoryPropertyFlagBits::eDeviceLocal;
42 properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
43 properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
44
45 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), 0);
46 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), -1);
47 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 0);
48}

◆ TEST() [31/399]

impeller::testing::TEST ( AllocatorVKTest  ,
MemoryTypeSelectionTwoHeap   
)

Definition at line 50 of file allocator_vk_unittests.cc.

50 {
51 vk::PhysicalDeviceMemoryProperties properties;
52 properties.memoryTypeCount = 2;
53 properties.memoryHeapCount = 2;
54 properties.memoryTypes[0].heapIndex = 0;
55 properties.memoryTypes[0].propertyFlags =
56 vk::MemoryPropertyFlagBits::eHostVisible;
57 properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
58 properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
59
60 properties.memoryTypes[1].heapIndex = 1;
61 properties.memoryTypes[1].propertyFlags =
62 vk::MemoryPropertyFlagBits::eDeviceLocal;
63 properties.memoryHeaps[1].size = 1024 * 1024 * 1024;
64 properties.memoryHeaps[1].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
65
66 // First fails because this only looks for eDeviceLocal.
67 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), -1);
68 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), 1);
69 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 1);
70 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(4, properties), -1);
71}

◆ TEST() [32/399]

impeller::testing::TEST ( AllocatorVKTest  ,
ToVKImageUsageFlags   
)

Definition at line 16 of file allocator_vk_unittests.cc.

16 {
17 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
18 PixelFormat::kR8G8B8A8UNormInt,
19 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
20 StorageMode::kDeviceTransient,
21 /*supports_memoryless_textures=*/true),
22 vk::ImageUsageFlagBits::eInputAttachment |
23 vk::ImageUsageFlagBits::eColorAttachment |
24 vk::ImageUsageFlagBits::eTransientAttachment);
25
26 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
27 PixelFormat::kD24UnormS8Uint,
28 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
29 StorageMode::kDeviceTransient,
30 /*supports_memoryless_textures=*/true),
31 vk::ImageUsageFlagBits::eDepthStencilAttachment |
32 vk::ImageUsageFlagBits::eTransientAttachment);
33}

◆ TEST() [33/399]

impeller::testing::TEST ( BaseTest  ,
CanUseTypedMasks   
)

Definition at line 266 of file base_unittests.cc.

266 {
267 {
268 MyMask mask;
269 ASSERT_EQ(static_cast<uint32_t>(mask), 0u);
270 ASSERT_FALSE(mask);
271 }
272
273 {
274 MyMask mask(MyMaskBits::kBar);
275 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
276 ASSERT_TRUE(mask);
277 }
278
279 {
280 MyMask mask2(MyMaskBits::kBar);
281 MyMask mask(mask2);
282 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
283 ASSERT_TRUE(mask);
284 }
285
286 {
287 MyMask mask2(MyMaskBits::kBar);
288 MyMask mask(std::move(mask2)); // NOLINT
289 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
290 ASSERT_TRUE(mask);
291 }
292
293 ASSERT_LT(MyMaskBits::kBar, MyMaskBits::kBaz);
294 ASSERT_LE(MyMaskBits::kBar, MyMaskBits::kBaz);
295 ASSERT_GT(MyMaskBits::kBaz, MyMaskBits::kBar);
296 ASSERT_GE(MyMaskBits::kBaz, MyMaskBits::kBar);
297 ASSERT_EQ(MyMaskBits::kBaz, MyMaskBits::kBaz);
298 ASSERT_NE(MyMaskBits::kBaz, MyMaskBits::kBang);
299
300 {
301 MyMask m1(MyMaskBits::kBar);
302 MyMask m2(MyMaskBits::kBaz);
303 ASSERT_EQ(static_cast<uint32_t>(m1 & m2), 0u);
304 ASSERT_FALSE(m1 & m2);
305 }
306
307 {
308 MyMask m1(MyMaskBits::kBar);
309 MyMask m2(MyMaskBits::kBaz);
310 ASSERT_EQ(static_cast<uint32_t>(m1 | m2), ((1u << 0u) | (1u << 1u)));
311 ASSERT_TRUE(m1 | m2);
312 }
313
314 {
315 MyMask m1(MyMaskBits::kBar);
316 MyMask m2(MyMaskBits::kBaz);
317 ASSERT_EQ(static_cast<uint32_t>(m1 ^ m2), ((1u << 0u) ^ (1u << 1u)));
318 ASSERT_TRUE(m1 ^ m2);
319 }
320
321 {
322 MyMask m1(MyMaskBits::kBar);
323 ASSERT_EQ(static_cast<uint32_t>(~m1), (~(1u << 0u)));
324 ASSERT_TRUE(m1);
325 }
326
327 {
328 MyMask m1 = MyMaskBits::kBar;
329 MyMask m2 = MyMaskBits::kBaz;
330 m2 = m1;
331 ASSERT_EQ(m2, MyMaskBits::kBar);
332 }
333
334 {
335 MyMask m = MyMaskBits::kBar | MyMaskBits::kBaz;
336 ASSERT_TRUE(m);
337 }
338
339 {
340 MyMask m = MyMaskBits::kBar & MyMaskBits::kBaz;
341 ASSERT_FALSE(m);
342 }
343
344 {
345 MyMask m = MyMaskBits::kBar ^ MyMaskBits::kBaz;
346 ASSERT_TRUE(m);
347 }
348
349 {
350 MyMask m = ~MyMaskBits::kBar;
351 ASSERT_TRUE(m);
352 }
353
354 {
355 MyMask m1 = MyMaskBits::kBar;
356 MyMask m2 = MyMaskBits::kBaz;
357 m2 |= m1;
358 ASSERT_EQ(m1, MyMaskBits::kBar);
359 MyMask pred = MyMaskBits::kBar | MyMaskBits::kBaz;
360 ASSERT_EQ(m2, pred);
361 }
362
363 {
364 MyMask m1 = MyMaskBits::kBar;
365 MyMask m2 = MyMaskBits::kBaz;
366 m2 &= m1;
367 ASSERT_EQ(m1, MyMaskBits::kBar);
368 MyMask pred = MyMaskBits::kBar & MyMaskBits::kBaz;
369 ASSERT_EQ(m2, pred);
370 }
371
372 {
373 MyMask m1 = MyMaskBits::kBar;
374 MyMask m2 = MyMaskBits::kBaz;
375 m2 ^= m1;
376 ASSERT_EQ(m1, MyMaskBits::kBar);
377 MyMask pred = MyMaskBits::kBar ^ MyMaskBits::kBaz;
378 ASSERT_EQ(m2, pred);
379 }
380
381 {
382 MyMask x = MyMaskBits::kBar;
383 MyMask m = x | MyMaskBits::kBaz;
384 ASSERT_TRUE(m);
385 }
386
387 {
388 MyMask x = MyMaskBits::kBar;
389 MyMask m = MyMaskBits::kBaz | x;
390 ASSERT_TRUE(m);
391 }
392
393 {
394 MyMask x = MyMaskBits::kBar;
395 MyMask m = x & MyMaskBits::kBaz;
396 ASSERT_FALSE(m);
397 }
398
399 {
400 MyMask x = MyMaskBits::kBar;
401 MyMask m = MyMaskBits::kBaz & x;
402 ASSERT_FALSE(m);
403 }
404
405 {
406 MyMask x = MyMaskBits::kBar;
407 MyMask m = x ^ MyMaskBits::kBaz;
408 ASSERT_TRUE(m);
409 }
410
411 {
412 MyMask x = MyMaskBits::kBar;
413 MyMask m = MyMaskBits::kBaz ^ x;
414 ASSERT_TRUE(m);
415 }
416
417 {
418 MyMask x = MyMaskBits::kBar;
419 MyMask m = ~x;
420 ASSERT_TRUE(m);
421 }
422
423 {
424 MyMaskBits x = MyMaskBits::kBar;
425 MyMask m = MyMaskBits::kBaz;
426 ASSERT_TRUE(x < m);
427 ASSERT_TRUE(x <= m);
428 }
429
430 {
431 MyMaskBits x = MyMaskBits::kBar;
432 MyMask m = MyMaskBits::kBaz;
433 ASSERT_FALSE(x == m);
434 }
435
436 {
437 MyMaskBits x = MyMaskBits::kBar;
438 MyMask m = MyMaskBits::kBaz;
439 ASSERT_TRUE(x != m);
440 }
441
442 {
443 MyMaskBits x = MyMaskBits::kBar;
444 MyMask m = MyMaskBits::kBaz;
445 ASSERT_FALSE(x > m);
446 ASSERT_FALSE(x >= m);
447 }
448}
@ kBar
skvx::Vec< 2, uint32_t > mask2
Mask< MyMaskBits > MyMask

◆ TEST() [34/399]

impeller::testing::TEST ( BaseTest  ,
NoExceptionPromiseEmpty   
)

Definition at line 257 of file base_unittests.cc.

257 {
258 auto wrapper = std::make_shared<NoExceptionPromise<int>>();
259 std::future future = wrapper->get_future();
260
261 // Destroy the empty promise with the future still pending. Verify that the
262 // process does not abort while destructing the promise.
263 wrapper.reset();
264}

◆ TEST() [35/399]

impeller::testing::TEST ( BaseTest  ,
NoExceptionPromiseValue   
)

Definition at line 250 of file base_unittests.cc.

250 {
252 std::future future = wrapper.get_future();
253 wrapper.set_value(123);
254 ASSERT_EQ(future.get(), 123);
255}
std::future< T > get_future()
Definition promise.h:36
void set_value(const T &value)
Definition promise.h:38

◆ TEST() [36/399]

impeller::testing::TEST ( BlitCommandVkTest  ,
BlitCopyBufferToTextureCommandVK   
)

Definition at line 49 of file blit_command_vk_unittests.cc.

49 {
50 auto context = MockVulkanContextBuilder().Build();
51 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
53 cmd.destination = context->GetResourceAllocator()->CreateTexture({
54 .format = PixelFormat::kR8G8B8A8UNormInt,
55 .size = ISize(100, 100),
56 });
57 cmd.source =
58 DeviceBuffer::AsBufferView(context->GetResourceAllocator()->CreateBuffer({
59 .size = 1,
60 }));
61 bool result = cmd.Encode(*encoder.get());
63 EXPECT_TRUE(encoder->IsTracking(cmd.source.buffer));
64 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
65}
std::shared_ptr< ContextVK > Build()
Create a Vulkan context with Vulkan functions mocked. The caller is given a chance to tinker on the s...
#define EXPECT_TRUE(handle)
Definition unit_test.h:685

◆ TEST() [37/399]

impeller::testing::TEST ( BlitCommandVkTest  ,
BlitCopyTextureToBufferCommandVK   
)

Definition at line 32 of file blit_command_vk_unittests.cc.

32 {
33 auto context = MockVulkanContextBuilder().Build();
34 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
36 cmd.source = context->GetResourceAllocator()->CreateTexture({
37 .format = PixelFormat::kR8G8B8A8UNormInt,
38 .size = ISize(100, 100),
39 });
40 cmd.destination = context->GetResourceAllocator()->CreateBuffer({
41 .size = 1,
42 });
43 bool result = cmd.Encode(*encoder.get());
45 EXPECT_TRUE(encoder->IsTracking(cmd.source));
46 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
47}

◆ TEST() [38/399]

impeller::testing::TEST ( BlitCommandVkTest  ,
BlitCopyTextureToTextureCommandVK   
)

Definition at line 13 of file blit_command_vk_unittests.cc.

13 {
14 auto context = MockVulkanContextBuilder().Build();
15 auto pool = context->GetCommandPoolRecycler()->Get();
16 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
18 cmd.source = context->GetResourceAllocator()->CreateTexture({
19 .format = PixelFormat::kR8G8B8A8UNormInt,
20 .size = ISize(100, 100),
21 });
22 cmd.destination = context->GetResourceAllocator()->CreateTexture({
23 .format = PixelFormat::kR8G8B8A8UNormInt,
24 .size = ISize(100, 100),
25 });
26 bool result = cmd.Encode(*encoder.get());
28 EXPECT_TRUE(encoder->IsTracking(cmd.source));
29 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
30}
AutoreleasePool pool

◆ TEST() [39/399]

impeller::testing::TEST ( BlitCommandVkTest  ,
BlitGenerateMipmapCommandVK   
)

Definition at line 67 of file blit_command_vk_unittests.cc.

67 {
68 auto context = MockVulkanContextBuilder().Build();
69 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
71 cmd.texture = context->GetResourceAllocator()->CreateTexture({
72 .format = PixelFormat::kR8G8B8A8UNormInt,
73 .size = ISize(100, 100),
74 .mip_count = 2,
75 });
76 bool result = cmd.Encode(*encoder.get());
78 EXPECT_TRUE(encoder->IsTracking(cmd.texture));
79}

◆ TEST() [40/399]

impeller::testing::TEST ( CanvasRecorder  ,
ClipOval   
)

Definition at line 227 of file canvas_recorder_unittests.cc.

227 {
228 CanvasRecorder<Serializer> recorder;
229 recorder.ClipOval({});
230 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipOval);
231}

◆ TEST() [41/399]

impeller::testing::TEST ( CanvasRecorder  ,
ClipPath   
)

Definition at line 215 of file canvas_recorder_unittests.cc.

215 {
216 CanvasRecorder<Serializer> recorder;
217 recorder.ClipPath({});
218 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipPath);
219}

◆ TEST() [42/399]

impeller::testing::TEST ( CanvasRecorder  ,
ClipRect   
)

Definition at line 221 of file canvas_recorder_unittests.cc.

221 {
222 CanvasRecorder<Serializer> recorder;
223 recorder.ClipRect({});
224 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipRect);
225}

◆ TEST() [43/399]

impeller::testing::TEST ( CanvasRecorder  ,
ClipRRect   
)

Definition at line 233 of file canvas_recorder_unittests.cc.

233 {
234 CanvasRecorder<Serializer> recorder;
235 recorder.ClipRRect({}, {});
236 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipRRect);
237}

◆ TEST() [44/399]

impeller::testing::TEST ( CanvasRecorder  ,
Concat   
)

Definition at line 106 of file canvas_recorder_unittests.cc.

106 {
107 CanvasRecorder<Serializer> recorder;
108 recorder.Concat(Matrix());
109 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kConcat);
110}
A 4x4 matrix using column-major storage.
Definition matrix.h:37

◆ TEST() [45/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawAtlas   
)

Definition at line 254 of file canvas_recorder_unittests.cc.

254 {
255 CanvasRecorder<Serializer> recorder;
256 recorder.DrawAtlas({}, {}, {}, {}, {}, {}, {}, {});
257 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawAtlas);
258}

◆ TEST() [46/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawCircle   
)

Definition at line 190 of file canvas_recorder_unittests.cc.

190 {
191 CanvasRecorder<Serializer> recorder;
192 recorder.DrawCircle(Point(), 0, Paint());
193 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawCircle);
194}

◆ TEST() [47/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawImage   
)

Definition at line 202 of file canvas_recorder_unittests.cc.

202 {
203 CanvasRecorder<Serializer> recorder;
204 recorder.DrawImage({}, {}, {}, {});
205 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawImage);
206}

◆ TEST() [48/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawImageRect   
)

Definition at line 208 of file canvas_recorder_unittests.cc.

208 {
209 CanvasRecorder<Serializer> recorder;
210 recorder.DrawImageRect({}, {}, {}, {}, {}, SourceRectConstraint::kFast);
211 ASSERT_EQ(recorder.GetSerializer().last_op_,
212 CanvasRecorderOp::kDrawImageRect);
213}

◆ TEST() [49/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawLine   
)

Definition at line 163 of file canvas_recorder_unittests.cc.

163 {
164 CanvasRecorder<Serializer> recorder;
165 recorder.DrawLine(Point(), Point(), Paint());
166 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawLine);
167}

◆ TEST() [50/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawOval   
)

Definition at line 178 of file canvas_recorder_unittests.cc.

178 {
179 CanvasRecorder<Serializer> recorder;
180 recorder.DrawOval(Rect(), Paint());
181 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawOval);
182}

◆ TEST() [51/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawPaint   
)

Definition at line 154 of file canvas_recorder_unittests.cc.

154 {
155 CanvasRecorder<Serializer> recorder;
156 Paint paint;
157 paint.color = Color::Red();
158 recorder.DrawPaint(paint);
159 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPaint);
160 ASSERT_EQ(recorder.GetSerializer().last_paint_.color, paint.color);
161}

◆ TEST() [52/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawPath   
)

Definition at line 148 of file canvas_recorder_unittests.cc.

148 {
149 CanvasRecorder<Serializer> recorder;
150 recorder.DrawPath(Path(), Paint());
151 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPath);
152}

◆ TEST() [53/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawPoints   
)

Definition at line 196 of file canvas_recorder_unittests.cc.

196 {
197 CanvasRecorder<Serializer> recorder;
198 recorder.DrawPoints(std::vector<Point>{}, 0, Paint(), PointStyle::kRound);
199 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPoints);
200}

◆ TEST() [54/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawRect   
)

Definition at line 169 of file canvas_recorder_unittests.cc.

169 {
170 CanvasRecorder<Serializer> recorder;
171 Paint paint;
172 paint.color = Color::Blue();
173 recorder.DrawRect(Rect(), paint);
174 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawRect);
175 ASSERT_EQ(recorder.GetSerializer().last_paint_.color, paint.color);
176}

◆ TEST() [55/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawRRect   
)

Definition at line 184 of file canvas_recorder_unittests.cc.

184 {
185 CanvasRecorder<Serializer> recorder;
186 recorder.DrawRRect(Rect(), {}, Paint());
187 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawRRect);
188}

◆ TEST() [56/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawTextFrame   
)

Definition at line 239 of file canvas_recorder_unittests.cc.

239 {
240 CanvasRecorder<Serializer> recorder;
241 recorder.DrawTextFrame({}, {}, {});
242 ASSERT_EQ(recorder.GetSerializer().last_op_,
243 CanvasRecorderOp::kDrawTextFrame);
244}

◆ TEST() [57/399]

impeller::testing::TEST ( CanvasRecorder  ,
DrawVertices   
)

Definition at line 246 of file canvas_recorder_unittests.cc.

246 {
247 CanvasRecorder<Serializer> recorder;
248 auto geometry = std::shared_ptr<VerticesGeometry>(
249 new VerticesGeometry({}, {}, {}, {}, {}, {}));
250 recorder.DrawVertices(geometry, {}, {});
251 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawVertices);
252}
A geometry that is created from a vertices object.

◆ TEST() [58/399]

impeller::testing::TEST ( CanvasRecorder  ,
PreConcat   
)

Definition at line 112 of file canvas_recorder_unittests.cc.

112 {
113 CanvasRecorder<Serializer> recorder;
114 recorder.PreConcat(Matrix());
115 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kPreConcat);
116}

◆ TEST() [59/399]

impeller::testing::TEST ( CanvasRecorder  ,
ResetTransform   
)

Definition at line 93 of file canvas_recorder_unittests.cc.

93 {
94 CanvasRecorder<Serializer> recorder;
95 recorder.ResetTransform();
96 ASSERT_EQ(recorder.GetSerializer().last_op_,
97 CanvasRecorderOp::kResetTransform);
98}

◆ TEST() [60/399]

impeller::testing::TEST ( CanvasRecorder  ,
Restore   
)

Definition at line 79 of file canvas_recorder_unittests.cc.

79 {
80 CanvasRecorder<Serializer> recorder;
81 recorder.Restore();
82 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kRestore);
83}

◆ TEST() [61/399]

impeller::testing::TEST ( CanvasRecorder  ,
RestoreToCount   
)

Definition at line 85 of file canvas_recorder_unittests.cc.

85 {
86 CanvasRecorder<Serializer> recorder;
87 recorder.Save();
88 recorder.RestoreToCount(0);
89 ASSERT_EQ(recorder.GetSerializer().last_op_,
90 CanvasRecorderOp::kRestoreToCount);
91}

◆ TEST() [62/399]

impeller::testing::TEST ( CanvasRecorder  ,
Rotate   
)

Definition at line 142 of file canvas_recorder_unittests.cc.

142 {
143 CanvasRecorder<Serializer> recorder;
144 recorder.Rotate(Radians(0));
145 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kRotate);
146}

◆ TEST() [63/399]

impeller::testing::TEST ( CanvasRecorder  ,
Save   
)

Definition at line 66 of file canvas_recorder_unittests.cc.

66 {
67 CanvasRecorder<Serializer> recorder;
68 recorder.Save();
69 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSave);
70}

◆ TEST() [64/399]

impeller::testing::TEST ( CanvasRecorder  ,
SaveLayer   
)

Definition at line 72 of file canvas_recorder_unittests.cc.

72 {
73 CanvasRecorder<Serializer> recorder;
75 recorder.SaveLayer(paint);
76 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSaveLayer);
77}

◆ TEST() [65/399]

impeller::testing::TEST ( CanvasRecorder  ,
Scale2   
)

Definition at line 124 of file canvas_recorder_unittests.cc.

124 {
125 CanvasRecorder<Serializer> recorder;
126 recorder.Scale(Vector2());
127 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kScale2);
128}

◆ TEST() [66/399]

impeller::testing::TEST ( CanvasRecorder  ,
Scale3   
)

Definition at line 130 of file canvas_recorder_unittests.cc.

130 {
131 CanvasRecorder<Serializer> recorder;
132 recorder.Scale(Vector3());
133 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kScale3);
134}

◆ TEST() [67/399]

impeller::testing::TEST ( CanvasRecorder  ,
Skew   
)

Definition at line 136 of file canvas_recorder_unittests.cc.

136 {
137 CanvasRecorder<Serializer> recorder;
138 recorder.Skew(0, 0);
139 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSkew);
140}

◆ TEST() [68/399]

impeller::testing::TEST ( CanvasRecorder  ,
Transform   
)

Definition at line 100 of file canvas_recorder_unittests.cc.

100 {
101 CanvasRecorder<Serializer> recorder;
102 recorder.Transform(Matrix());
103 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kTransform);
104}

◆ TEST() [69/399]

impeller::testing::TEST ( CanvasRecorder  ,
Translate   
)

Definition at line 118 of file canvas_recorder_unittests.cc.

118 {
119 CanvasRecorder<Serializer> recorder;
120 recorder.Translate(Vector3());
121 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kTranslate);
122}

◆ TEST() [70/399]

impeller::testing::TEST ( CapabilitiesGLES  ,
CanInitializeWithDefaults   
)

Definition at line 13 of file capabilities_unittests.cc.

13 {
14 auto mock_gles = MockGLES::Init();
15
16 auto capabilities = mock_gles->GetProcTable().GetCapabilities();
17
18 EXPECT_FALSE(capabilities->SupportsOffscreenMSAA());
19 EXPECT_FALSE(capabilities->SupportsSSBO());
20 EXPECT_FALSE(capabilities->SupportsBufferToTextureBlits());
21 EXPECT_FALSE(capabilities->SupportsTextureToTextureBlits());
22 EXPECT_FALSE(capabilities->SupportsFramebufferFetch());
23 EXPECT_FALSE(capabilities->SupportsCompute());
24 EXPECT_FALSE(capabilities->SupportsComputeSubgroups());
25 EXPECT_FALSE(capabilities->SupportsReadFromResolve());
26 EXPECT_FALSE(capabilities->SupportsDecalSamplerAddressMode());
27 EXPECT_FALSE(capabilities->SupportsDeviceTransientTextures());
28
29 EXPECT_EQ(capabilities->GetDefaultColorFormat(),
30 PixelFormat::kR8G8B8A8UNormInt);
31 EXPECT_EQ(capabilities->GetDefaultStencilFormat(), PixelFormat::kS8UInt);
32 EXPECT_EQ(capabilities->GetDefaultDepthStencilFormat(),
33 PixelFormat::kD24UnormS8Uint);
34}

◆ TEST() [71/399]

impeller::testing::TEST ( CapabilitiesGLES  ,
SupportsDecalSamplerAddressMode   
)

Definition at line 36 of file capabilities_unittests.cc.

36 {
37 auto const extensions = std::vector<const unsigned char*>{
38 reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
39 reinterpret_cast<const unsigned char*>("GL_EXT_texture_border_clamp"), //
40 };
41 auto mock_gles = MockGLES::Init(extensions);
42 auto capabilities = mock_gles->GetProcTable().GetCapabilities();
43 EXPECT_TRUE(capabilities->SupportsDecalSamplerAddressMode());
44}

◆ TEST() [72/399]

impeller::testing::TEST ( CapabilitiesGLES  ,
SupportsDecalSamplerAddressModeNotOES   
)

Definition at line 46 of file capabilities_unittests.cc.

46 {
47 auto const extensions = std::vector<const unsigned char*>{
48 reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
49 reinterpret_cast<const unsigned char*>("GL_OES_texture_border_clamp"), //
50 };
51 auto mock_gles = MockGLES::Init(extensions);
52 auto capabilities = mock_gles->GetProcTable().GetCapabilities();
53 EXPECT_FALSE(capabilities->SupportsDecalSamplerAddressMode());
54}

◆ TEST() [73/399]

impeller::testing::TEST ( CapabilitiesGLES  ,
SupportsFramebufferFetch   
)

Definition at line 56 of file capabilities_unittests.cc.

56 {
57 auto const extensions = std::vector<const unsigned char*>{
58 reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
59 reinterpret_cast<const unsigned char*>(
60 "GL_EXT_shader_framebuffer_fetch"), //
61 };
62 auto mock_gles = MockGLES::Init(extensions);
63 auto capabilities = mock_gles->GetProcTable().GetCapabilities();
64 EXPECT_TRUE(capabilities->SupportsFramebufferFetch());
65}

◆ TEST() [74/399]

impeller::testing::TEST ( CapabilitiesTest  ,
DefaultColorFormat   
)

Definition at line 32 of file capabilities_unittests.cc.

32 {
33 auto defaults = CapabilitiesBuilder().Build();
34 EXPECT_EQ(defaults->GetDefaultColorFormat(), PixelFormat::kUnknown);
35 auto mutated = CapabilitiesBuilder()
36 .SetDefaultColorFormat(PixelFormat::kB10G10R10A10XR)
37 .Build();
38 EXPECT_EQ(mutated->GetDefaultColorFormat(), PixelFormat::kB10G10R10A10XR);
39}
CapabilitiesBuilder & SetDefaultColorFormat(PixelFormat value)
std::unique_ptr< Capabilities > Build()

◆ TEST() [75/399]

impeller::testing::TEST ( CapabilitiesTest  ,
DefaultDepthStencilFormat   
)

Definition at line 50 of file capabilities_unittests.cc.

50 {
51 auto defaults = CapabilitiesBuilder().Build();
52 EXPECT_EQ(defaults->GetDefaultDepthStencilFormat(), PixelFormat::kUnknown);
53 auto mutated = CapabilitiesBuilder()
54 .SetDefaultDepthStencilFormat(PixelFormat::kD32FloatS8UInt)
55 .Build();
56 EXPECT_EQ(mutated->GetDefaultDepthStencilFormat(),
57 PixelFormat::kD32FloatS8UInt);
58}
CapabilitiesBuilder & SetDefaultDepthStencilFormat(PixelFormat value)

◆ TEST() [76/399]

impeller::testing::TEST ( CapabilitiesTest  ,
DefaultGlyphAtlasFormat   
)

Definition at line 60 of file capabilities_unittests.cc.

60 {
61 auto defaults = CapabilitiesBuilder().Build();
62 EXPECT_EQ(defaults->GetDefaultGlyphAtlasFormat(), PixelFormat::kUnknown);
63 auto mutated = CapabilitiesBuilder()
64 .SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
65 .Build();
66 EXPECT_EQ(mutated->GetDefaultGlyphAtlasFormat(), PixelFormat::kA8UNormInt);
67}
CapabilitiesBuilder & SetDefaultGlyphAtlasFormat(PixelFormat value)

◆ TEST() [77/399]

impeller::testing::TEST ( CapabilitiesTest  ,
DefaultStencilFormat   
)

Definition at line 41 of file capabilities_unittests.cc.

41 {
42 auto defaults = CapabilitiesBuilder().Build();
43 EXPECT_EQ(defaults->GetDefaultStencilFormat(), PixelFormat::kUnknown);
44 auto mutated = CapabilitiesBuilder()
45 .SetDefaultStencilFormat(PixelFormat::kS8UInt)
46 .Build();
47 EXPECT_EQ(mutated->GetDefaultStencilFormat(), PixelFormat::kS8UInt);
48}
CapabilitiesBuilder & SetDefaultStencilFormat(PixelFormat value)

◆ TEST() [78/399]

impeller::testing::TEST ( CapabilitiesVKTest  ,
ContextFailsInitializationForNoCombinedDepthStencilFormat   
)

Definition at line 195 of file context_vk_unittests.cc.

196 {
197 ScopedValidationDisable disable_validation;
198 const std::shared_ptr<ContextVK> context =
201 [](VkPhysicalDevice physicalDevice, VkFormat format,
202 VkFormatProperties* pFormatProperties) {
204 pFormatProperties->optimalTilingFeatures =
205 static_cast<VkFormatFeatureFlags>(
206 vk::FormatFeatureFlagBits::eColorAttachment);
207 }
208 // Ignore combined depth-stencil formats.
209 })
210 .Build();
211 ASSERT_EQ(context, nullptr);
212}
MockVulkanContextBuilder & SetPhysicalDeviceFormatPropertiesCallback(std::function< void(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties)> format_properties_callback)
Definition mock_vulkan.h:94
uint32_t uint32_t * format
VkFormatFeatureFlags optimalTilingFeatures
VkFlags VkFormatFeatureFlags
VkFormat
@ VK_FORMAT_R8G8B8A8_UNORM

◆ TEST() [79/399]

impeller::testing::TEST ( CapabilitiesVKTest  ,
ContextInitializesWithNoStencilFormat   
)

Definition at line 164 of file context_vk_unittests.cc.

164 {
165 const std::shared_ptr<ContextVK> context =
168 [](VkPhysicalDevice physicalDevice, VkFormat format,
169 VkFormatProperties* pFormatProperties) {
171 pFormatProperties->optimalTilingFeatures =
172 static_cast<VkFormatFeatureFlags>(
173 vk::FormatFeatureFlagBits::eColorAttachment);
174 } else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
175 pFormatProperties->optimalTilingFeatures =
176 static_cast<VkFormatFeatureFlags>(
177 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
178 }
179 // Ignore just the stencil format.
180 })
181 .Build();
182 ASSERT_NE(context, nullptr);
183 const CapabilitiesVK* capabilites_vk =
184 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
185 ASSERT_EQ(capabilites_vk->GetDefaultDepthStencilFormat(),
186 PixelFormat::kD32FloatS8UInt);
187 ASSERT_EQ(capabilites_vk->GetDefaultStencilFormat(),
188 PixelFormat::kD32FloatS8UInt);
189}
Build(configs, env, options)
Definition build.py:232
@ VK_FORMAT_D32_SFLOAT_S8_UINT

◆ TEST() [80/399]

impeller::testing::TEST ( CommandEncoderVKTest  ,
CleanupAfterSubmit   
)

Definition at line 42 of file command_encoder_vk_unittests.cc.

42 {
43 // This tests deleting the TrackedObjects where the thread is killed before
44 // the fence waiter has disposed of them, making sure the command buffer and
45 // its pools are deleted in that order.
46 std::shared_ptr<std::vector<std::string>> called_functions;
47 {
48 fml::AutoResetWaitableEvent wait_for_submit;
49 fml::AutoResetWaitableEvent wait_for_thread_join;
50 auto context = MockVulkanContextBuilder().Build();
51 std::thread thread([&] {
52 auto buffer = context->CreateCommandBuffer();
53 context->GetCommandQueue()->Submit(
54 {buffer}, [&](CommandBuffer::Status status) {
55 ASSERT_EQ(status, CommandBuffer::Status::kCompleted);
56 wait_for_thread_join.Wait();
57 wait_for_submit.Signal();
58 });
59 });
60 thread.join();
61 wait_for_thread_join.Signal();
62 wait_for_submit.Wait();
63 called_functions = GetMockVulkanFunctions(context->GetDevice());
64 context->Shutdown();
65 }
66
67 auto destroy_pool =
68 std::find(called_functions->begin(), called_functions->end(),
69 "vkDestroyCommandPool");
70 auto free_buffers =
71 std::find(called_functions->begin(), called_functions->end(),
72 "vkFreeCommandBuffers");
73 EXPECT_TRUE(destroy_pool != called_functions->end());
74 EXPECT_TRUE(free_buffers != called_functions->end());
75 EXPECT_TRUE(free_buffers < destroy_pool);
76}
static const uint8_t buffer[]
std::shared_ptr< std::vector< std::string > > GetMockVulkanFunctions(VkDevice device)

◆ TEST() [81/399]

impeller::testing::TEST ( CommandEncoderVKTest  ,
DeleteEncoderAfterThreadDies   
)

Definition at line 16 of file command_encoder_vk_unittests.cc.

16 {
17 // Tests that when a CommandEncoderVK is deleted that it will clean up its
18 // command buffers before it cleans up its command pool.
19 std::shared_ptr<std::vector<std::string>> called_functions;
20 {
21 auto context = MockVulkanContextBuilder().Build();
22 called_functions = GetMockVulkanFunctions(context->GetDevice());
23 std::shared_ptr<CommandEncoderVK> encoder;
24 std::thread thread([&] {
25 CommandEncoderFactoryVK factory(context);
26 encoder = factory.Create();
27 });
28 thread.join();
29 context->Shutdown();
30 }
31 auto destroy_pool =
32 std::find(called_functions->begin(), called_functions->end(),
33 "vkDestroyCommandPool");
34 auto free_buffers =
35 std::find(called_functions->begin(), called_functions->end(),
36 "vkFreeCommandBuffers");
37 EXPECT_TRUE(destroy_pool != called_functions->end());
38 EXPECT_TRUE(free_buffers != called_functions->end());
39 EXPECT_TRUE(free_buffers < destroy_pool);
40}

◆ TEST() [82/399]

impeller::testing::TEST ( CommandPoolRecyclerVKTest  ,
CommandBuffersAreRecycled   
)

Definition at line 115 of file command_pool_vk_unittests.cc.

115 {
116 auto const context = MockVulkanContextBuilder().Build();
117
118 {
119 // Fetch a pool (which will be created).
120 auto const recycler = context->GetCommandPoolRecycler();
121 auto pool = recycler->Get();
122
123 auto buffer = pool->CreateCommandBuffer();
124 pool->CollectCommandBuffer(std::move(buffer));
125
126 // This normally is called at the end of a frame.
127 recycler->Dispose();
128 }
129
130 // Wait for the pool to be reclaimed.
131 for (auto i = 0u; i < 2u; i++) {
132 auto waiter = fml::AutoResetWaitableEvent();
133 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
134 {
135 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
136 std::move(rattle));
137 }
138 waiter.Wait();
139 }
140
141 {
142 // Create a second pool and command buffer, which should reused the existing
143 // pool and cmd buffer.
144 auto const recycler = context->GetCommandPoolRecycler();
145 auto pool = recycler->Get();
146
147 auto buffer = pool->CreateCommandBuffer();
148 pool->CollectCommandBuffer(std::move(buffer));
149
150 // This normally is called at the end of a frame.
151 recycler->Dispose();
152 }
153
154 // Now check that we only ever created one pool and one command buffer.
155 auto const called = GetMockVulkanFunctions(context->GetDevice());
156 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
157 1u);
158 EXPECT_EQ(
159 std::count(called->begin(), called->end(), "vkAllocateCommandBuffers"),
160 1u);
161
162 context->Shutdown();
163}

◆ TEST() [83/399]

impeller::testing::TEST ( CommandPoolRecyclerVKTest  ,
GetsACommandPoolPerThread   
)

Definition at line 14 of file command_pool_vk_unittests.cc.

14 {
15 auto const context = MockVulkanContextBuilder().Build();
16
17 {
18 // Record the memory location of each pointer to a command pool.
19 //
20 // These pools have to be held at this context, otherwise they will be
21 // dropped and recycled and potentially reused by another thread, causing
22 // flaky tests.
23 std::shared_ptr<CommandPoolVK> pool1;
24 std::shared_ptr<CommandPoolVK> pool2;
25
26 // Create a command pool in two threads and record the memory location.
27 std::thread thread1(
28 [&]() { pool1 = context->GetCommandPoolRecycler()->Get(); });
29
30 std::thread thread2(
31 [&]() { pool2 = context->GetCommandPoolRecycler()->Get(); });
32
33 thread1.join();
34 thread2.join();
35
36 // The two command pools should be different.
37 EXPECT_NE(pool1, pool2);
38 }
39
40 context->Shutdown();
41}

◆ TEST() [84/399]

impeller::testing::TEST ( CommandPoolRecyclerVKTest  ,
GetsTheSameCommandPoolOnSameThread   
)

Definition at line 43 of file command_pool_vk_unittests.cc.

43 {
44 auto const context = MockVulkanContextBuilder().Build();
45
46 auto const pool1 = context->GetCommandPoolRecycler()->Get();
47 auto const pool2 = context->GetCommandPoolRecycler()->Get();
48
49 // The two command pools should be the same.
50 EXPECT_EQ(pool1.get(), pool2.get());
51
52 context->Shutdown();
53}

◆ TEST() [85/399]

impeller::testing::TEST ( CommandPoolRecyclerVKTest  ,
ReclaimMakesCommandPoolAvailable   
)

Definition at line 76 of file command_pool_vk_unittests.cc.

76 {
77 auto const context = MockVulkanContextBuilder().Build();
78
79 {
80 // Fetch a pool (which will be created).
81 auto const recycler = context->GetCommandPoolRecycler();
82 auto const pool = recycler->Get();
83
84 // This normally is called at the end of a frame.
85 recycler->Dispose();
86 }
87
88 // Add something to the resource manager and have it notify us when it's
89 // destroyed. That should give us a non-flaky signal that the pool has been
90 // reclaimed as well.
91 auto waiter = fml::AutoResetWaitableEvent();
92 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
93 {
94 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
95 std::move(rattle));
96 }
97 waiter.Wait();
98
99 // On another thread explicitly, request a new pool.
100 std::thread thread([&]() {
101 auto const pool = context->GetCommandPoolRecycler()->Get();
102 EXPECT_NE(pool.get(), nullptr);
103 });
104
105 thread.join();
106
107 // Now check that we only ever created one pool.
108 auto const called = GetMockVulkanFunctions(context->GetDevice());
109 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
110 1u);
111
112 context->Shutdown();
113}
const GrXPFactory * Get(SkBlendMode mode)

◆ TEST() [86/399]

impeller::testing::TEST ( ConditionVariableTest  ,
TestsCriticalSectionAfterWait   
)

Definition at line 205 of file base_unittests.cc.

205 {
206 std::vector<std::thread> threads;
207 const auto kThreadCount = 10u;
208
209 Mutex mtx;
211 size_t sum = 0u;
212
213 std::condition_variable start_cv;
214 std::mutex start_mtx;
215 bool start = false;
216 auto start_predicate = [&start]() { return start; };
217 auto thread_main = [&]() {
218 {
219 std::unique_lock start_lock(start_mtx);
220 start_cv.wait(start_lock, start_predicate);
221 }
222
223 mtx.Lock();
224 cv.Wait(mtx, []() { return true; });
225 auto old_val = sum;
226 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
227 sum = old_val + 1u;
228 mtx.Unlock();
229 };
230 // Launch all threads. They will wait for the start CV to be signaled.
231 for (size_t i = 0; i < kThreadCount; i++) {
232 threads.emplace_back(thread_main);
233 }
234 // Notify all threads that the test may start.
235 {
236 {
237 std::scoped_lock start_lock(start_mtx);
238 start = true;
239 }
240 start_cv.notify_all();
241 }
242 // Join all threads.
243 ASSERT_EQ(threads.size(), kThreadCount);
244 for (size_t i = 0; i < kThreadCount; i++) {
245 threads[i].join();
246 }
247 ASSERT_EQ(sum, kThreadCount);
248}
A condition variable exactly similar to the one in libcxx with two major differences:
Definition thread.h:146
void Wait(Mutex &mutex, const Predicate &should_stop_waiting) IPLR_REQUIRES(mutex)
Atomically unlocks the mutex and waits on the condition variable indefinitely till the predicate dete...
Definition thread.h:260
static constexpr uint64_t kThreadCount

◆ TEST() [87/399]

impeller::testing::TEST ( ConditionVariableTest  ,
TestsCriticalSectionAfterWaitForUntil   
)

Definition at line 160 of file base_unittests.cc.

160 {
161 std::vector<std::thread> threads;
162 const auto kThreadCount = 10u;
163
164 Mutex mtx;
166 size_t sum = 0u;
167
168 std::condition_variable start_cv;
169 std::mutex start_mtx;
170 bool start = false;
171 auto start_predicate = [&start]() { return start; };
172 auto thread_main = [&]() {
173 {
174 std::unique_lock start_lock(start_mtx);
175 start_cv.wait(start_lock, start_predicate);
176 }
177
178 mtx.Lock();
179 cv.WaitFor(mtx, std::chrono::milliseconds{0u}, []() { return true; });
180 auto old_val = sum;
181 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
182 sum = old_val + 1u;
183 mtx.Unlock();
184 };
185 // Launch all threads. They will wait for the start CV to be signaled.
186 for (size_t i = 0; i < kThreadCount; i++) {
187 threads.emplace_back(thread_main);
188 }
189 // Notify all threads that the test may start.
190 {
191 {
192 std::scoped_lock start_lock(start_mtx);
193 start = true;
194 }
195 start_cv.notify_all();
196 }
197 // Join all threads.
198 ASSERT_EQ(threads.size(), kThreadCount);
199 for (size_t i = 0; i < kThreadCount; i++) {
200 threads[i].join();
201 }
202 ASSERT_EQ(sum, kThreadCount);
203}
bool WaitFor(Mutex &mutex, const std::chrono::duration< Representation, Period > &duration, const Predicate &should_stop_waiting) IPLR_REQUIRES(mutex)
Atomically unlocks the mutex and waits on the condition variable for a designated duration....
Definition thread.h:231

◆ TEST() [88/399]

impeller::testing::TEST ( ConditionVariableTest  ,
WaitFor   
)

Definition at line 122 of file base_unittests.cc.

122 {
123 CVTest test;
124 // test.rando_ivar = 12; // <--- Static analysis error
125 for (size_t i = 0; i < 2; ++i) {
126 test.mutex.Lock(); // <--- Static analysis error without this.
127 auto result = test.cv.WaitFor(
128 test.mutex, std::chrono::milliseconds{10},
129 [&]() IPLR_REQUIRES(test.mutex) {
130 test.rando_ivar = 12; // <-- Static analysics error without the
131 // IPLR_REQUIRES on the pred.
132 return false;
133 });
134 test.mutex.Unlock();
135 ASSERT_FALSE(result);
136 }
137 Lock lock(test.mutex); // <--- Static analysis error without this.
138 // The predicate never returns true. So return has to be due to a non-spurious
139 // wake.
140 ASSERT_EQ(test.rando_ivar, 12u);
141}
#define test(name)
#define IPLR_REQUIRES(...)

◆ TEST() [89/399]

impeller::testing::TEST ( ConditionVariableTest  ,
WaitForever   
)

Definition at line 143 of file base_unittests.cc.

143 {
144 CVTest test;
145 // test.rando_ivar = 12; // <--- Static analysis error
146 for (size_t i = 0; i < 2; ++i) {
147 test.mutex.Lock(); // <--- Static analysis error without this.
148 test.cv.Wait(test.mutex, [&]() IPLR_REQUIRES(test.mutex) {
149 test.rando_ivar = 12; // <-- Static analysics error without
150 // the IPLR_REQUIRES on the pred.
151 return true;
152 });
153 test.mutex.Unlock();
154 }
155 Lock lock(test.mutex); // <--- Static analysis error without this.
156 // The wake only happens when the predicate returns true.
157 ASSERT_EQ(test.rando_ivar, 12u);
158}

◆ TEST() [90/399]

impeller::testing::TEST ( ConditionVariableTest  ,
WaitUntil   
)

Definition at line 99 of file base_unittests.cc.

99 {
100 CVTest test;
101 // test.rando_ivar = 12; // <--- Static analysis error
102 for (size_t i = 0; i < 2; ++i) {
103 test.mutex.Lock(); // <--- Static analysis error without this.
104 auto result = test.cv.WaitUntil(
105 test.mutex,
106 std::chrono::high_resolution_clock::now() +
107 std::chrono::milliseconds{10},
108 [&]() IPLR_REQUIRES(test.mutex) {
109 test.rando_ivar = 12; // <-- Static analysics error without the
110 // IPLR_REQUIRES on the pred.
111 return false;
112 });
113 test.mutex.Unlock();
114 ASSERT_FALSE(result);
115 }
116 Lock lock(test.mutex); // <--- Static analysis error without this.
117 // The predicate never returns true. So return has to be due to a non-spurious
118 // wake.
119 ASSERT_EQ(test.rando_ivar, 12u);
120}

◆ TEST() [91/399]

impeller::testing::TEST ( ContentContext  ,
CachesPipelines   
)

Definition at line 262 of file content_context_unittests.cc.

262 {
263 auto context = std::make_shared<FakeContext>();
264
265 auto create_callback = [&]() {
266 return std::make_shared<FakePipeline>(context->GetPipelineLibrary(),
268 };
269
270 ContentContext content_context(context, nullptr);
271 ContentContextOptions optionsA{.blend_mode = BlendMode::kSourceOver};
272 ContentContextOptions optionsB{.blend_mode = BlendMode::kSource};
273
274 auto pipelineA = content_context.GetCachedRuntimeEffectPipeline(
275 "A", optionsA, create_callback);
276
277 auto pipelineA2 = content_context.GetCachedRuntimeEffectPipeline(
278 "A", optionsA, create_callback);
279
280 auto pipelineA3 = content_context.GetCachedRuntimeEffectPipeline(
281 "A", optionsB, create_callback);
282
283 auto pipelineB = content_context.GetCachedRuntimeEffectPipeline(
284 "B", optionsB, create_callback);
285
286 ASSERT_EQ(pipelineA.get(), pipelineA2.get());
287 ASSERT_NE(pipelineA.get(), pipelineA3.get());
288 ASSERT_NE(pipelineB.get(), pipelineA.get());
289}

◆ TEST() [92/399]

impeller::testing::TEST ( ContentContext  ,
InitializeCommonlyUsedShadersIfNeeded   
)

Definition at line 337 of file content_context_unittests.cc.

337 {
338 ScopedValidationFatal fatal_validations;
339 // Set a pixel format that is larger than 32bpp.
340 auto context = std::make_shared<FakeContext>("Mali G70",
341 PixelFormat::kR16G16B16A16Float);
342 ContentContext content_context(context, nullptr);
343
344 FakeAllocator& fake_allocator =
345 FakeAllocator::Cast(*context->GetResourceAllocator());
346
347#if IMPELLER_ENABLE_3D
348 EXPECT_EQ(fake_allocator.textures.size(), 2u);
349#else
350 EXPECT_EQ(fake_allocator.textures.size(), 1u);
351#endif // IMPELLER_ENABLE_3D
352}

◆ TEST() [93/399]

impeller::testing::TEST ( ContentContext  ,
InvalidatesAllPipelinesWithSameUniqueNameOnClear   
)

Definition at line 291 of file content_context_unittests.cc.

291 {
292 auto context = std::make_shared<FakeContext>();
293 ContentContext content_context(context, nullptr);
294 ContentContextOptions optionsA{.blend_mode = BlendMode::kSourceOver};
295 ContentContextOptions optionsB{.blend_mode = BlendMode::kSource};
296
297 auto create_callback = [&]() {
298 return std::make_shared<FakePipeline>(context->GetPipelineLibrary(),
299 PipelineDescriptor{});
300 };
301
302 auto pipelineA = content_context.GetCachedRuntimeEffectPipeline(
303 "A", optionsA, create_callback);
304
305 auto pipelineA2 = content_context.GetCachedRuntimeEffectPipeline(
306 "A", optionsB, create_callback);
307
308 auto pipelineB = content_context.GetCachedRuntimeEffectPipeline(
309 "B", optionsB, create_callback);
310
311 ASSERT_TRUE(pipelineA);
312 ASSERT_TRUE(pipelineA2);
313 ASSERT_TRUE(pipelineB);
314
315 ASSERT_EQ(pipelineA, content_context.GetCachedRuntimeEffectPipeline(
316 "A", optionsA, create_callback));
317 ASSERT_EQ(pipelineA2, content_context.GetCachedRuntimeEffectPipeline(
318 "A", optionsB, create_callback));
319 ASSERT_EQ(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
320 "B", optionsB, create_callback));
321
322 content_context.ClearCachedRuntimeEffectPipeline("A");
323
324 ASSERT_NE(pipelineA, content_context.GetCachedRuntimeEffectPipeline(
325 "A", optionsA, create_callback));
326 ASSERT_NE(pipelineA2, content_context.GetCachedRuntimeEffectPipeline(
327 "A", optionsB, create_callback));
328 ASSERT_EQ(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
329 "B", optionsB, create_callback));
330
331 content_context.ClearCachedRuntimeEffectPipeline("B");
332
333 ASSERT_NE(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
334 "B", optionsB, create_callback));
335}

◆ TEST() [94/399]

impeller::testing::TEST ( ContextVKTest  ,
CanCreateContextInAbsenceOfValidationLayers   
)

Definition at line 132 of file context_vk_unittests.cc.

132 {
133 // The mocked methods don't report the presence of a validation layer but we
134 // explicitly ask for validation. Context creation should continue anyway.
135 auto context = MockVulkanContextBuilder()
136 .SetSettingsCallback([](auto& settings) {
137 settings.enable_validation = true;
138 })
139 .Build();
140 ASSERT_NE(context, nullptr);
141 const CapabilitiesVK* capabilites_vk =
142 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
143 ASSERT_FALSE(capabilites_vk->AreValidationsEnabled());
144}
The Vulkan layers and extensions wrangler.
MockVulkanContextBuilder & SetSettingsCallback(const std::function< void(ContextVK::Settings &)> &settings_callback)
Definition mock_vulkan.h:74

◆ TEST() [95/399]

impeller::testing::TEST ( ContextVKTest  ,
CanCreateContextWithValidationLayers   
)

Definition at line 146 of file context_vk_unittests.cc.

146 {
147 auto context =
150 [](auto& settings) { settings.enable_validation = true; })
151 .SetInstanceExtensions(
152 {"VK_KHR_surface", "VK_MVK_macos_surface", "VK_EXT_debug_utils"})
153 .SetInstanceLayers({"VK_LAYER_KHRONOS_validation"})
154 .Build();
155 ASSERT_NE(context, nullptr);
156 const CapabilitiesVK* capabilites_vk =
157 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
158 ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
159}

◆ TEST() [96/399]

impeller::testing::TEST ( ContextVKTest  ,
CommonHardwareConcurrencyConfigurations   
)

Definition at line 16 of file context_vk_unittests.cc.

16 {
17 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(100u), 4u);
18 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(9u), 4u);
19 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(8u), 4u);
20 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(7u), 3u);
21 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(6u), 3u);
22 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(5u), 2u);
23 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(4u), 2u);
24 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(3u), 1u);
25 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(2u), 1u);
26 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(1u), 1u);
27}

◆ TEST() [97/399]

impeller::testing::TEST ( ContextVKTest  ,
DeletePipelineAfterContext   
)

Definition at line 75 of file context_vk_unittests.cc.

75 {
76 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
77 std::shared_ptr<std::vector<std::string>> functions;
78 {
79 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
80 PipelineDescriptor pipeline_desc;
81 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
83 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
84 pipeline = pipeline_future.Get();
85 ASSERT_TRUE(pipeline);
86 functions = GetMockVulkanFunctions(context->GetDevice());
87 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
88 "vkCreateGraphicsPipelines") != functions->end());
89 }
90 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
91 "vkDestroyDevice") != functions->end());
92}
PipelineDescriptor & SetVertexDescriptor(std::shared_ptr< VertexDescriptor > vertex_descriptor)
const std::shared_ptr< Pipeline< T > > Get() const
Definition pipeline.h:29

◆ TEST() [98/399]

impeller::testing::TEST ( ContextVKTest  ,
DeletePipelineLibraryAfterContext   
)

Definition at line 116 of file context_vk_unittests.cc.

116 {
117 std::shared_ptr<PipelineLibrary> pipeline_library;
118 std::shared_ptr<std::vector<std::string>> functions;
119 {
120 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
121 PipelineDescriptor pipeline_desc;
122 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
123 pipeline_library = context->GetPipelineLibrary();
124 functions = GetMockVulkanFunctions(context->GetDevice());
125 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
126 "vkCreatePipelineCache") != functions->end());
127 }
128 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
129 "vkDestroyDevice") != functions->end());
130}

◆ TEST() [99/399]

impeller::testing::TEST ( ContextVKTest  ,
DeletesCommandPools   
)

Definition at line 29 of file context_vk_unittests.cc.

29 {
30 std::weak_ptr<ContextVK> weak_context;
31 std::weak_ptr<CommandPoolVK> weak_pool;
32 {
33 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
34 auto const pool = context->GetCommandPoolRecycler()->Get();
35 weak_pool = pool;
36 weak_context = context;
37 ASSERT_TRUE(weak_pool.lock());
38 ASSERT_TRUE(weak_context.lock());
39 }
40 ASSERT_FALSE(weak_pool.lock());
41 ASSERT_FALSE(weak_context.lock());
42}

◆ TEST() [100/399]

impeller::testing::TEST ( ContextVKTest  ,
DeletesCommandPoolsOnAllThreads   
)

Definition at line 44 of file context_vk_unittests.cc.

44 {
45 std::weak_ptr<ContextVK> weak_context;
46 std::weak_ptr<CommandPoolVK> weak_pool_main;
47
48 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
49 weak_pool_main = context->GetCommandPoolRecycler()->Get();
50 weak_context = context;
51 ASSERT_TRUE(weak_pool_main.lock());
52 ASSERT_TRUE(weak_context.lock());
53
54 // Start a second thread that obtains a command pool.
55 fml::AutoResetWaitableEvent latch1, latch2;
56 std::weak_ptr<CommandPoolVK> weak_pool_thread;
57 std::thread thread([&]() {
58 weak_pool_thread = context->GetCommandPoolRecycler()->Get();
59 latch1.Signal();
60 latch2.Wait();
61 });
62
63 // Delete the ContextVK on the main thread.
64 latch1.Wait();
65 context.reset();
66 ASSERT_FALSE(weak_pool_main.lock());
67 ASSERT_FALSE(weak_context.lock());
68
69 // Stop the second thread and check that its command pool has been deleted.
70 latch2.Signal();
71 thread.join();
72 ASSERT_FALSE(weak_pool_thread.lock());
73}

◆ TEST() [101/399]

impeller::testing::TEST ( ContextVKTest  ,
DeleteShaderFunctionAfterContext   
)

Definition at line 94 of file context_vk_unittests.cc.

94 {
95 std::shared_ptr<const ShaderFunction> shader_function;
96 std::shared_ptr<std::vector<std::string>> functions;
97 {
98 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
99 PipelineDescriptor pipeline_desc;
100 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
101 std::vector<uint8_t> data = {0x03, 0x02, 0x23, 0x07};
102 context->GetShaderLibrary()->RegisterFunction(
103 "foobar_fragment_main", ShaderStage::kFragment,
104 std::make_shared<fml::DataMapping>(data), [](bool) {});
105 shader_function = context->GetShaderLibrary()->GetFunction(
106 "foobar_fragment_main", ShaderStage::kFragment);
107 ASSERT_TRUE(shader_function);
108 functions = GetMockVulkanFunctions(context->GetDevice());
109 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
110 "vkCreateShaderModule") != functions->end());
111 }
112 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
113 "vkDestroyDevice") != functions->end());
114}

◆ TEST() [102/399]

impeller::testing::TEST ( ContextVKTest  ,
FatalMissingValidations   
)

Definition at line 225 of file context_vk_unittests.cc.

225 {
226 EXPECT_DEATH(const std::shared_ptr<ContextVK> context =
228 .SetSettingsCallback([](ContextVK::Settings& settings) {
229 settings.enable_validation = true;
230 settings.fatal_missing_validations = true;
231 })
232 .Build(),
233 "");
234}

◆ TEST() [103/399]

impeller::testing::TEST ( ContextVKTest  ,
HasDefaultColorFormat   
)

Definition at line 236 of file context_vk_unittests.cc.

236 {
237 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
238
239 const CapabilitiesVK* capabilites_vk =
240 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
241 ASSERT_NE(capabilites_vk->GetDefaultColorFormat(), PixelFormat::kUnknown);
242}
PixelFormat GetDefaultColorFormat() const override
Returns a supported PixelFormat for textures that store 4-channel colors (red/green/blue/alpha).

◆ TEST() [104/399]

impeller::testing::TEST ( ContextVKTest  ,
WarmUpFunctionCreatesRenderPass   
)

Definition at line 214 of file context_vk_unittests.cc.

214 {
215 const std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
216
217 context->SetOffscreenFormat(PixelFormat::kR8G8B8A8UNormInt);
218 context->InitializeCommonlyUsedShadersIfNeeded();
219
220 auto functions = GetMockVulkanFunctions(context->GetDevice());
221 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
222 "vkCreateRenderPass") != functions->end());
223}

◆ TEST() [105/399]

impeller::testing::TEST ( DescriptorPoolRecyclerVKTest  ,
GetDescriptorPoolRecyclerCreatesNewPools   
)

Definition at line 15 of file descriptor_pool_vk_unittests.cc.

15 {
16 auto const context = MockVulkanContextBuilder().Build();
17
18 auto const pool1 = context->GetDescriptorPoolRecycler()->Get();
19 auto const pool2 = context->GetDescriptorPoolRecycler()->Get();
20
21 // The two descriptor pools should be different.
22 EXPECT_NE(pool1.get(), pool2.get());
23
24 context->Shutdown();
25}

◆ TEST() [106/399]

impeller::testing::TEST ( DescriptorPoolRecyclerVKTest  ,
ReclaimDropsDescriptorPoolIfSizeIsExceeded   
)

Definition at line 65 of file descriptor_pool_vk_unittests.cc.

65 {
66 auto const context = MockVulkanContextBuilder().Build();
67
68 // Create 33 pools
69 {
70 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
71 for (auto i = 0u; i < 33; i++) {
72 auto pool = std::make_unique<DescriptorPoolVK>(context);
73 pool->AllocateDescriptorSets({}, *context);
74 pools.push_back(std::move(pool));
75 }
76 }
77
78 // See note above.
79 for (auto i = 0u; i < 2; i++) {
80 auto waiter = fml::AutoResetWaitableEvent();
81 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
82 {
83 UniqueResourceVKT<fml::ScopedCleanupClosure> resource(
84 context->GetResourceManager(), std::move(rattle));
85 }
86 waiter.Wait();
87 }
88
89 auto const called = GetMockVulkanFunctions(context->GetDevice());
90 EXPECT_EQ(
91 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
92 33u);
93 EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetDescriptorPool"),
94 33u);
95
96 // Now create 33 more descriptor pools and observe that only one more is
97 // allocated.
98 {
99 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
100 for (auto i = 0u; i < 33; i++) {
101 auto pool = std::make_unique<DescriptorPoolVK>(context);
102 pool->AllocateDescriptorSets({}, *context);
103 pools.push_back(std::move(pool));
104 }
105 }
106
107 for (auto i = 0u; i < 2; i++) {
108 auto waiter = fml::AutoResetWaitableEvent();
109 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
110 {
111 UniqueResourceVKT<fml::ScopedCleanupClosure> resource(
112 context->GetResourceManager(), std::move(rattle));
113 }
114 waiter.Wait();
115 }
116
117 auto const called_twice = GetMockVulkanFunctions(context->GetDevice());
118 // 32 of the descriptor pools were recycled, so only one more is created.
119 EXPECT_EQ(
120 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
121 34u);
122
123 context->Shutdown();
124}
Wraps a closure that is invoked in the destructor unless released by the caller.
Definition closure.h:32

◆ TEST() [107/399]

impeller::testing::TEST ( DescriptorPoolRecyclerVKTest  ,
ReclaimMakesDescriptorPoolAvailable   
)

Definition at line 27 of file descriptor_pool_vk_unittests.cc.

27 {
28 auto const context = MockVulkanContextBuilder().Build();
29
30 {
31 // Fetch a pool (which will be created).
32 auto pool = DescriptorPoolVK(context);
33 pool.AllocateDescriptorSets({}, *context);
34 }
35
36 // There is a chance that the first death rattle item below is destroyed in
37 // the same reclaim cycle as the pool allocation above. These items are placed
38 // into a std::vector and free'd, which may free in reverse order. That would
39 // imply that the death rattle and subsequent waitable event fires before the
40 // pool is reset. To work around this, we can either manually remove items
41 // from the vector or use two death rattles.
42 for (auto i = 0u; i < 2; i++) {
43 // Add something to the resource manager and have it notify us when it's
44 // destroyed. That should give us a non-flaky signal that the pool has been
45 // reclaimed as well.
46 auto waiter = fml::AutoResetWaitableEvent();
47 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
48 {
49 UniqueResourceVKT<fml::ScopedCleanupClosure> resource(
50 context->GetResourceManager(), std::move(rattle));
51 }
52 waiter.Wait();
53 }
54
55 auto const pool = context->GetDescriptorPoolRecycler()->Get();
56
57 // Now check that we only ever created one pool.
58 auto const called = GetMockVulkanFunctions(context->GetDevice());
59 EXPECT_EQ(
60 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"), 1u);
61
62 context->Shutdown();
63}
A per-frame descriptor pool. Descriptors from this pool don't need to be freed individually....

◆ TEST() [108/399]

impeller::testing::TEST ( DisplayListTest  ,
CircleBoundsComputation   
)

Definition at line 1789 of file dl_unittests.cc.

1789 {
1790 SkPath path = SkPath().addCircle(0, 0, 5);
1791
1794
1795 builder.DrawPath(path, paint);
1796 auto display_list = builder.Build();
1797
1798 DlDispatcher dispatcher;
1799 display_list->Dispatch(dispatcher);
1800 auto picture = dispatcher.EndRecordingAsPicture();
1801
1802 std::optional<Rect> coverage =
1803 GetCoverageOfFirstEntity<SolidColorContents>(picture);
1804
1805 ASSERT_TRUE(coverage.has_value());
1806 ASSERT_EQ(coverage.value_or(Rect::MakeMaximum()),
1807 Rect::MakeLTRB(-5, -5, 5, 5));
1808}
SkPath & addCircle(SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:1149

◆ TEST() [109/399]

impeller::testing::TEST ( DisplayListTest  ,
RRectBoundsComputation   
)

Definition at line 1766 of file dl_unittests.cc.

1766 {
1767 SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 100, 100), 4, 4);
1768 SkPath path = SkPath().addRRect(rrect);
1769
1772
1773 builder.DrawPath(path, paint);
1774 auto display_list = builder.Build();
1775
1776 DlDispatcher dispatcher;
1777 display_list->Dispatch(dispatcher);
1778 auto picture = dispatcher.EndRecordingAsPicture();
1779
1780 std::optional<Rect> coverage =
1781 GetCoverageOfFirstEntity<SolidColorContents>(picture);
1782
1783 // Validate that the RRect coverage is _exactly_ the same as the input rect.
1784 ASSERT_TRUE(coverage.has_value());
1785 ASSERT_EQ(coverage.value_or(Rect::MakeMaximum()),
1786 Rect::MakeLTRB(0, 0, 100, 100));
1787}
SkPath & addRRect(const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:990
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition SkRRect.h:180
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646

◆ TEST() [110/399]

impeller::testing::TEST ( EntityGeometryTest  ,
FillPathGeometryCoversArea   
)

Definition at line 76 of file geometry_unittests.cc.

76 {
77 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
78 auto geometry = Geometry::MakeFillPath(
79 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
80 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
81 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
82 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
83 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
84}
Path TakePath(FillType fill=FillType::kNonZero)

◆ TEST() [111/399]

impeller::testing::TEST ( EntityGeometryTest  ,
FillPathGeometryCoversAreaNoInnerRect   
)

Definition at line 86 of file geometry_unittests.cc.

86 {
87 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
88 auto geometry = Geometry::MakeFillPath(path);
89 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
90 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
91 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
92 ASSERT_FALSE(geometry->CoversArea({}, Rect()));
93}

◆ TEST() [112/399]

impeller::testing::TEST ( EntityGeometryTest  ,
GeometryResultHasReasonableDefaults   
)

Definition at line 130 of file geometry_unittests.cc.

130 {
132 EXPECT_EQ(result.type, PrimitiveType::kTriangleStrip);
133 EXPECT_EQ(result.transform, Matrix());
134 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
135}

◆ TEST() [113/399]

impeller::testing::TEST ( EntityGeometryTest  ,
LineGeometryCoverage   
)

Definition at line 95 of file geometry_unittests.cc.

95 {
96 {
97 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kButt);
98 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(10, 9, 20, 11));
99 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(10, 9, 20, 11)));
100 }
101
102 {
103 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kSquare);
104 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 21, 11));
105 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 21, 11)));
106 }
107
108 {
109 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kButt);
110 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 10, 11, 20));
111 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 10, 11, 20)));
112 }
113
114 {
115 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kSquare);
116 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 11, 21));
117 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 11, 21)));
118 }
119}

◆ TEST() [114/399]

impeller::testing::TEST ( EntityGeometryTest  ,
RectGeometryCoversArea   
)

Definition at line 68 of file geometry_unittests.cc.

68 {
69 auto geometry = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 100, 100));
70 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
71 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
72 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
73 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
74}

◆ TEST() [115/399]

impeller::testing::TEST ( EntityGeometryTest  ,
RoundRectGeometryCoversArea   
)

Definition at line 121 of file geometry_unittests.cc.

121 {
122 auto geometry =
123 Geometry::MakeRoundRect(Rect::MakeLTRB(0, 0, 100, 100), Size(20, 20));
124 EXPECT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(15, 15, 85, 85)));
125 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(20, 20, 80, 80)));
126 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(30, 1, 70, 99)));
127 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70)));
128}

◆ TEST() [116/399]

impeller::testing::TEST ( EntityPassClipStackTest  ,
AppendAndRestoreClipCoverage   
)

Definition at line 92 of file entity_pass_unittests.cc.

92 {
93 EntityPassClipStack recorder =
94 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
95
96 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
97
98 // Push a clip.
99 Entity entity;
102 .type = Contents::ClipCoverage::Type::kAppend,
103 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
104 },
105 entity, 0, Point(0, 0));
106 EXPECT_TRUE(result.should_render);
107 EXPECT_TRUE(result.clip_did_change);
108
109 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
110 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
111 Rect::MakeLTRB(50, 50, 55, 55));
112 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
113 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
114
115 // Restore the clip.
116 auto restore_clip = std::make_shared<ClipRestoreContents>();
117 restore_clip->SetRestoreHeight(0);
118 entity.SetContents(std::move(restore_clip));
119 recorder.ApplyClipState(
121 .type = Contents::ClipCoverage::Type::kRestore,
122 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
123 },
124 entity, 0, Point(0, 0));
125
126 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
127 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
128 Rect::MakeSize(Size::MakeWH(100, 100)));
129 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
130 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
131}
A class that tracks all clips that have been recorded in the current entity pass stencil.
const std::vector< ReplayResult > & GetReplayEntities() const
ClipStateResult ApplyClipState(Contents::ClipCoverage global_clip_coverage, Entity &entity, size_t clip_height_floor, Point global_pass_position)
Applies the current clip state to an Entity. If the given Entity is a clip operation,...
const std::vector< ClipCoverageLayer > GetClipCoverageLayers() const

◆ TEST() [117/399]

impeller::testing::TEST ( EntityPassClipStackTest  ,
AppendCoverageNoChange   
)

Definition at line 69 of file entity_pass_unittests.cc.

69 {
70 EntityPassClipStack recorder =
71 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
72
73 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
74 Rect::MakeSize(Size::MakeWH(100, 100)));
75 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
76
77 Entity entity;
80 .type = Contents::ClipCoverage::Type::kNoChange,
81 .coverage = std::nullopt,
82 },
83 entity, 0, Point(0, 0));
84 EXPECT_TRUE(result.should_render);
85 EXPECT_FALSE(result.clip_did_change);
86
87 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
88 Rect::MakeSize(Size::MakeWH(100, 100)));
89 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
90}

◆ TEST() [118/399]

impeller::testing::TEST ( EntityPassClipStackTest  ,
CanAppendNoChange   
)

Definition at line 57 of file entity_pass_unittests.cc.

57 {
58 EntityPassClipStack recorder =
59 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
60
61 EXPECT_TRUE(recorder.GetReplayEntities().empty());
62
63 Entity entity;
64 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kNoChange,
65 Rect());
66 EXPECT_TRUE(recorder.GetReplayEntities().empty());
67}
void RecordEntity(const Entity &entity, Contents::ClipCoverage::Type type, std::optional< Rect > clip_coverage)

◆ TEST() [119/399]

impeller::testing::TEST ( EntityPassClipStackTest  ,
CanPopEntitiesSafely   
)

Definition at line 46 of file entity_pass_unittests.cc.

46 {
47 EntityPassClipStack recorder =
48 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
49
50 EXPECT_TRUE(recorder.GetReplayEntities().empty());
51
52 Entity entity;
53 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
54 EXPECT_TRUE(recorder.GetReplayEntities().empty());
55}

◆ TEST() [120/399]

impeller::testing::TEST ( EntityPassClipStackTest  ,
CanPushAndPopEntities   
)

Definition at line 16 of file entity_pass_unittests.cc.

16 {
17 EntityPassClipStack recorder =
18 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
19
20 EXPECT_TRUE(recorder.GetReplayEntities().empty());
21
22 Entity entity;
23 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
24 Rect::MakeLTRB(0, 0, 100, 100));
25 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
26
27 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
28 Rect::MakeLTRB(0, 0, 50, 50));
29 EXPECT_EQ(recorder.GetReplayEntities().size(), 2u);
30 ASSERT_TRUE(recorder.GetReplayEntities()[0].clip_coverage.has_value());
31 ASSERT_TRUE(recorder.GetReplayEntities()[1].clip_coverage.has_value());
32 // NOLINTBEGIN(bugprone-unchecked-optional-access)
33 EXPECT_EQ(recorder.GetReplayEntities()[0].clip_coverage.value(),
34 Rect::MakeLTRB(0, 0, 100, 100));
35 EXPECT_EQ(recorder.GetReplayEntities()[1].clip_coverage.value(),
36 Rect::MakeLTRB(0, 0, 50, 50));
37 // NOLINTEND(bugprone-unchecked-optional-access)
38
39 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
40 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
41
42 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
43 EXPECT_TRUE(recorder.GetReplayEntities().empty());
44}

◆ TEST() [121/399]

impeller::testing::TEST ( EntityPassClipStackTest  ,
ClipAndRestoreWithSubpasses   
)

Definition at line 160 of file entity_pass_unittests.cc.

160 {
161 EntityPassClipStack recorder =
162 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
163
164 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
165
166 // Push a clip.
167 Entity entity;
168 {
171 .type = Contents::ClipCoverage::Type::kAppend,
172 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
173 },
174 entity, 0, Point(0, 0));
175 EXPECT_TRUE(result.should_render);
176 EXPECT_TRUE(result.clip_did_change);
177 }
178
179 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
180 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
181 Rect::MakeLTRB(50, 50, 55, 55));
182 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
183 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
184
185 // Begin a subpass.
186 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
187 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
188 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
189 Rect::MakeLTRB(50, 50, 55, 55));
190
191 {
192 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
193 Contents::ClipCoverage{
194 .type = Contents::ClipCoverage::Type::kAppend,
195 .coverage = Rect::MakeLTRB(54, 54, 55, 55),
196 },
197 entity, 0, Point(0, 0));
198 EXPECT_TRUE(result.should_render);
199 EXPECT_TRUE(result.clip_did_change);
200 }
201
202 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
203 Rect::MakeLTRB(54, 54, 55, 55));
204
205 // End subpass.
206 recorder.PopSubpass();
207
208 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
209 Rect::MakeLTRB(50, 50, 55, 55));
210}
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_height)
TPoint< Scalar > Point
Definition point.h:316

◆ TEST() [122/399]

impeller::testing::TEST ( EntityPassClipStackTest  ,
UnbalancedRestore   
)

Definition at line 133 of file entity_pass_unittests.cc.

133 {
134 EntityPassClipStack recorder =
135 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
136
137 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
138
139 // Restore the clip.
140 Entity entity;
141 auto restore_clip = std::make_shared<ClipRestoreContents>();
142 restore_clip->SetRestoreHeight(0);
143 entity.SetContents(std::move(restore_clip));
146 .type = Contents::ClipCoverage::Type::kRestore,
147 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
148 },
149 entity, 0, Point(0, 0));
150 EXPECT_FALSE(result.should_render);
151 EXPECT_FALSE(result.clip_did_change);
152
153 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
154 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
155 Rect::MakeSize(Size::MakeWH(100, 100)));
156 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
157 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
158}

◆ TEST() [123/399]

impeller::testing::TEST ( FenceWaiterVKTest  ,
AddFenceDoesNothingIfTerminating   
)

Definition at line 86 of file fence_waiter_vk_unittests.cc.

86 {
87 auto signal = fml::ManualResetWaitableEvent();
88
89 {
90 auto const context = MockVulkanContextBuilder().Build();
91 auto const device = context->GetDevice();
92 auto const waiter = context->GetFenceWaiter();
93 waiter->Terminate();
94
95 auto fence = device.createFenceUnique({}).value;
96 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
97 }
98
99 // Ensure the fence did _not_ signal.
100 EXPECT_TRUE(signal.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(100)));
101}
static constexpr TimeDelta FromMilliseconds(int64_t millis)
Definition time_delta.h:46

◆ TEST() [124/399]

impeller::testing::TEST ( FenceWaiterVKTest  ,
ExecutesFenceCallback   
)

Definition at line 28 of file fence_waiter_vk_unittests.cc.

28 {
29 auto const context = MockVulkanContextBuilder().Build();
30 auto const device = context->GetDevice();
31 auto const waiter = context->GetFenceWaiter();
32
33 auto signal = fml::ManualResetWaitableEvent();
34 auto fence = device.createFenceUnique({}).value;
35 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
36
37 signal.Wait();
38}

◆ TEST() [125/399]

impeller::testing::TEST ( FenceWaiterVKTest  ,
ExecutesFenceCallbackX2   
)

Definition at line 40 of file fence_waiter_vk_unittests.cc.

40 {
41 auto const context = MockVulkanContextBuilder().Build();
42 auto const device = context->GetDevice();
43 auto const waiter = context->GetFenceWaiter();
44
45 auto signal = fml::ManualResetWaitableEvent();
46 auto fence = device.createFenceUnique({}).value;
47 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
48
49 auto signal2 = fml::ManualResetWaitableEvent();
50 auto fence2 = device.createFenceUnique({}).value;
51 waiter->AddFence(std::move(fence2), [&signal2]() { signal2.Signal(); });
52
53 signal.Wait();
54 signal2.Wait();
55}

◆ TEST() [126/399]

impeller::testing::TEST ( FenceWaiterVKTest  ,
ExecutesNewFenceThenOldFence   
)

Definition at line 57 of file fence_waiter_vk_unittests.cc.

57 {
58 auto const context = MockVulkanContextBuilder().Build();
59 auto const device = context->GetDevice();
60 auto const waiter = context->GetFenceWaiter();
61
62 auto signal = fml::ManualResetWaitableEvent();
63 auto fence = device.createFenceUnique({}).value;
64 MockFence::SetStatus(fence, vk::Result::eNotReady);
65 auto raw_fence = MockFence::GetRawPointer(fence);
66 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
67
68 // The easiest way to verify that the callback was _not_ called is to wait
69 // for a timeout, but that could introduce flakiness. Instead, we'll add a
70 // second fence that will signal immediately, and wait for that one instead.
71 {
72 auto signal2 = fml::ManualResetWaitableEvent();
73 auto fence2 = device.createFenceUnique({}).value;
74 MockFence::SetStatus(fence2, vk::Result::eSuccess);
75 waiter->AddFence(std::move(fence2), [&signal2]() { signal2.Signal(); });
76 signal2.Wait();
77 }
78
79 // Now, we'll signal the first fence, and wait for the callback to be called.
80 raw_fence->SetStatus(vk::Result::eSuccess);
81
82 // Now, we'll signal the first fence, and wait for the callback to be called.
83 signal.Wait();
84}

◆ TEST() [127/399]

impeller::testing::TEST ( FenceWaiterVKTest  ,
IgnoresNullCallback   
)

Definition at line 19 of file fence_waiter_vk_unittests.cc.

19 {
20 auto const context = MockVulkanContextBuilder().Build();
21 auto const device = context->GetDevice();
22 auto const waiter = context->GetFenceWaiter();
23
24 auto fence = device.createFenceUnique({}).value;
25 EXPECT_FALSE(waiter->AddFence(std::move(fence), nullptr));
26}

◆ TEST() [128/399]

impeller::testing::TEST ( FenceWaiterVKTest  ,
IgnoresNullFence   
)

Definition at line 13 of file fence_waiter_vk_unittests.cc.

13 {
14 auto const context = MockVulkanContextBuilder().Build();
15 auto const waiter = context->GetFenceWaiter();
16 EXPECT_FALSE(waiter->AddFence(vk::UniqueFence(), []() {}));
17}

◆ TEST() [129/399]

impeller::testing::TEST ( FenceWaiterVKTest  ,
InProgressFencesStillWaitIfTerminated   
)

Definition at line 103 of file fence_waiter_vk_unittests.cc.

103 {
104 MockFence* raw_fence = nullptr;
105 auto signal = fml::ManualResetWaitableEvent();
106
107 auto const context = MockVulkanContextBuilder().Build();
108 auto const device = context->GetDevice();
109 auto const waiter = context->GetFenceWaiter();
110
111 // Add a fence that isn't signalled yet.
112 auto fence = device.createFenceUnique({}).value;
113
114 // Even if the fence is eSuccess, it's not guaranteed to be called in time.
115 MockFence::SetStatus(fence, vk::Result::eNotReady);
116 raw_fence = MockFence::GetRawPointer(fence);
117 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
118
119 // Terminate the waiter.
120 waiter->Terminate();
121
122 // Signal the fence.
123 raw_fence->SetStatus(vk::Result::eSuccess);
124
125 // This will hang if the fence was not signalled.
126 signal.Wait();
127}
void SetStatus(vk::Result result)
Definition mock_vulkan.h:33

◆ TEST() [130/399]

impeller::testing::TEST ( FilterInputTest  ,
CanSetLocalTransformForTexture   
)

Definition at line 17 of file filter_input_unittests.cc.

17 {
18 std::shared_ptr<Texture> texture = nullptr;
19 auto input =
20 FilterInput::Make(texture, Matrix::MakeTranslation({1.0, 0.0, 0.0}));
21 Entity e;
22 e.SetTransform(Matrix::MakeTranslation({0.0, 2.0, 0.0}));
23
24 ASSERT_MATRIX_NEAR(input->GetLocalTransform(e),
25 Matrix::MakeTranslation({1.0, 0.0, 0.0}));
26 ASSERT_MATRIX_NEAR(input->GetTransform(e),
27 Matrix::MakeTranslation({1.0, 2.0, 0.0}));
28}
#define ASSERT_MATRIX_NEAR(a, b)
FlTexture * texture

◆ TEST() [131/399]

impeller::testing::TEST ( FilterInputTest  ,
IsLeaf   
)

Definition at line 30 of file filter_input_unittests.cc.

30 {
31 std::shared_ptr<FilterContents> leaf =
32 ColorFilterContents::MakeBlend(BlendMode::kSource, {});
33 ASSERT_TRUE(leaf->IsLeaf());
34
35 auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
36 Matrix(), {});
37
38 ASSERT_TRUE(leaf->IsLeaf());
39 ASSERT_FALSE(base->IsLeaf());
40}

◆ TEST() [132/399]

impeller::testing::TEST ( FilterInputTest  ,
SetCoverageInputs   
)

Definition at line 42 of file filter_input_unittests.cc.

42 {
43 std::shared_ptr<FilterContents> leaf =
44 ColorFilterContents::MakeBlend(BlendMode::kSource, {});
45 ASSERT_TRUE(leaf->IsLeaf());
46
47 auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
48 Matrix(), {});
49
50 {
51 auto result = base->GetCoverage({});
52 ASSERT_FALSE(result.has_value());
53 }
54
55 auto coverage_rect = Rect::MakeLTRB(100, 100, 200, 200);
56 base->SetLeafInputs(FilterInput::Make({coverage_rect}));
57
58 {
59 auto result = base->GetCoverage({});
60 ASSERT_TRUE(result.has_value());
61 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
62 ASSERT_RECT_NEAR(result.value(), coverage_rect);
63 }
64}
#define ASSERT_RECT_NEAR(a, b)

◆ TEST() [133/399]

impeller::testing::TEST ( FormatsGLES  ,
CanFormatFramebufferErrorMessage   
)

Definition at line 12 of file formats_gles_unittests.cc.

12 {
13 ASSERT_EQ(DebugToFramebufferError(GL_FRAMEBUFFER_UNDEFINED),
14 "GL_FRAMEBUFFER_UNDEFINED");
15 ASSERT_EQ(DebugToFramebufferError(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
16 "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
17 ASSERT_EQ(
18 DebugToFramebufferError(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
19 "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
20 ASSERT_EQ(DebugToFramebufferError(GL_FRAMEBUFFER_UNSUPPORTED),
21 "GL_FRAMEBUFFER_UNSUPPORTED");
22 ASSERT_EQ(DebugToFramebufferError(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE),
23 "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE");
24 ASSERT_EQ(DebugToFramebufferError(0), "Unknown error code: 0");
25}
std::string DebugToFramebufferError(int status)

◆ TEST() [134/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
CalculateSigmaForBlurRadius   
)

Definition at line 445 of file gaussian_blur_filter_contents_unittests.cc.

445 {
446 Scalar sigma = 1.0;
447 Scalar radius = GaussianBlurFilterContents::CalculateBlurRadius(
448 GaussianBlurFilterContents::ScaleSigma(sigma));
449 fml::StatusOr<Scalar> derived_sigma =
450 CalculateSigmaForBlurRadius(radius, Matrix());
451 ASSERT_TRUE(derived_sigma.ok());
452 EXPECT_NEAR(sigma, derived_sigma.value(), 0.01f);
453}
const T & value() const
Definition status_or.h:77
bool ok() const
Definition status_or.h:75

◆ TEST() [135/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
CalculateSigmaValues   
)

Definition at line 216 of file gaussian_blur_filter_contents_unittests.cc.

216 {
217 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
218 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
219 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
220 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
221 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
222 // Hang on to 1/8 as long as possible.
223 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(95.0f), 0.125);
224 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(96.0f), 0.0625);
225 // Downsample clamped to 1/16th.
226 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 0.0625);
227}

◆ TEST() [136/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
Coefficients   
)

Definition at line 455 of file gaussian_blur_filter_contents_unittests.cc.

455 {
456 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
457 .blur_sigma = 1,
458 .blur_radius = 5,
459 .step_size = 1};
460 GaussianBlurPipeline::FragmentShader::KernelSamples samples =
461 GenerateBlurInfo(parameters);
462 EXPECT_EQ(samples.sample_count, 9);
463
464 // Coefficients should add up to 1.
465 Scalar tally = 0;
466 for (int i = 0; i < samples.sample_count; ++i) {
467 tally += samples.samples[i].coefficient;
468 }
469 EXPECT_FLOAT_EQ(tally, 1.0f);
470
471 // Verify the shape of the curve.
472 for (int i = 0; i < 4; ++i) {
473 EXPECT_FLOAT_EQ(samples.samples[i].coefficient,
474 samples.samples[8 - i].coefficient);
475 EXPECT_TRUE(samples.samples[i + 1].coefficient >
476 samples.samples[i].coefficient);
477 }
478}
GaussianBlurPipeline::FragmentShader::KernelSamples GenerateBlurInfo(BlurParameters parameters)

◆ TEST() [137/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
CoverageEmpty   
)

Definition at line 112 of file gaussian_blur_filter_contents_unittests.cc.

112 {
114 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
115 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
116 FilterInput::Vector inputs = {};
117 Entity entity;
118 std::optional<Rect> coverage =
119 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
120 ASSERT_FALSE(coverage.has_value());
121}
std::vector< FilterInput::Ref > Vector

◆ TEST() [138/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
CoverageSimple   
)

Definition at line 123 of file gaussian_blur_filter_contents_unittests.cc.

123 {
125 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
126 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
127 FilterInput::Vector inputs = {
128 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
129 Entity entity;
130 std::optional<Rect> coverage =
131 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
132
133 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
134}

◆ TEST() [139/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
CoverageWithSigma   
)

Definition at line 136 of file gaussian_blur_filter_contents_unittests.cc.

136 {
137 fml::StatusOr<Scalar> sigma_radius_1 =
138 CalculateSigmaForBlurRadius(1.0, Matrix());
139 ASSERT_TRUE(sigma_radius_1.ok());
141 /*sigma_x=*/sigma_radius_1.value(),
142 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
143 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
144 FilterInput::Vector inputs = {
145 FilterInput::Make(Rect::MakeLTRB(100, 100, 200, 200))};
146 Entity entity;
147 std::optional<Rect> coverage =
148 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
149
150 EXPECT_TRUE(coverage.has_value());
151 if (coverage.has_value()) {
152 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
153 }
154}
#define EXPECT_RECT_NEAR(a, b)

◆ TEST() [140/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
Create   
)

Definition at line 104 of file gaussian_blur_filter_contents_unittests.cc.

104 {
106 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
107 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
108 EXPECT_EQ(contents.GetSigmaX(), 0.0);
109 EXPECT_EQ(contents.GetSigmaY(), 0.0);
110}

◆ TEST() [141/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
FilterSourceCoverage   
)

Definition at line 199 of file gaussian_blur_filter_contents_unittests.cc.

199 {
200 fml::StatusOr<Scalar> sigma_radius_1 =
201 CalculateSigmaForBlurRadius(1.0, Matrix());
202 ASSERT_TRUE(sigma_radius_1.ok());
203 auto contents = std::make_unique<GaussianBlurFilterContents>(
204 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
205 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
206 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
207 /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
208 /*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
209 EXPECT_TRUE(coverage.has_value());
210 if (coverage.has_value()) {
211 EXPECT_RECT_NEAR(coverage.value(),
212 Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
213 }
214}

◆ TEST() [142/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
LerpHackKernelSamplesComplex   
)

Definition at line 558 of file gaussian_blur_filter_contents_unittests.cc.

558 {
559 Scalar sigma = 10.0f;
560 int32_t blur_radius = static_cast<int32_t>(
561 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
562 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
563 .blur_sigma = sigma,
564 .blur_radius = blur_radius,
565 .step_size = 1};
566 GaussianBlurPipeline::FragmentShader::KernelSamples kernel_samples =
567 GenerateBlurInfo(parameters);
568 EXPECT_EQ(kernel_samples.sample_count, 33);
569 GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples =
570 LerpHackKernelSamples(kernel_samples);
571 EXPECT_EQ(fast_kernel_samples.sample_count, 17);
572 float data[33];
573 srand(0);
574 for (int i = 0; i < 33; i++) {
575 data[i] = 255.0 * static_cast<double>(IMPELLER_RAND()) / RAND_MAX;
576 }
577
578 auto sampler = [data](Point point) -> Scalar {
579 FML_CHECK(point.y == 0.0f);
580 FML_CHECK(point.x >= -16);
581 FML_CHECK(point.x <= 16);
582 Scalar fint_part;
583 Scalar fract = fabsf(modf(point.x, &fint_part));
584 if (fract == 0) {
585 int32_t int_part = static_cast<int32_t>(fint_part) + 16;
586 return data[int_part];
587 } else {
588 int32_t left = static_cast<int32_t>(floor(point.x)) + 16;
589 int32_t right = static_cast<int32_t>(ceil(point.x)) + 16;
590 if (point.x < 0) {
591 return fract * data[left] + (1.0 - fract) * data[right];
592 } else {
593 return (1.0 - fract) * data[left] + fract * data[right];
594 }
595 }
596 };
597
598 Scalar output = 0.0;
599 for (int i = 0; i < kernel_samples.sample_count; ++i) {
600 auto sample = kernel_samples.samples[i];
601 output += sample.coefficient * sampler(sample.uv_offset);
602 }
603
604 Scalar fast_output = 0.0;
605 for (int i = 0; i < fast_kernel_samples.sample_count; ++i) {
606 auto sample = fast_kernel_samples.samples[i];
607 fast_output += sample.coefficient * sampler(sample.uv_offset);
608 }
609
610 EXPECT_NEAR(output, fast_output, 0.1);
611}
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define FML_CHECK(condition)
Definition logging.h:85
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(GaussianBlurPipeline::FragmentShader::KernelSamples parameters)
SIN Vec< N, float > fract(const Vec< N, float > &x)
Definition SkVx.h:744
SIN Vec< N, float > floor(const Vec< N, float > &x)
Definition SkVx.h:703
SIN Vec< N, float > ceil(const Vec< N, float > &x)
Definition SkVx.h:702

◆ TEST() [143/399]

impeller::testing::TEST ( GaussianBlurFilterContentsTest  ,
LerpHackKernelSamplesSimple   
)

Definition at line 480 of file gaussian_blur_filter_contents_unittests.cc.

480 {
481 GaussianBlurPipeline::FragmentShader::KernelSamples kernel_samples = {
482 .sample_count = 5,
483 .samples =
484 {
485 {
486 .uv_offset = Vector2(-2, 0),
487 .coefficient = 0.1f,
488 },
489 {
490 .uv_offset = Vector2(-1, 0),
491 .coefficient = 0.2f,
492 },
493 {
494 .uv_offset = Vector2(0, 0),
495 .coefficient = 0.4f,
496 },
497 {
498 .uv_offset = Vector2(1, 0),
499 .coefficient = 0.2f,
500 },
501 {
502 .uv_offset = Vector2(2, 0),
503 .coefficient = 0.1f,
504 },
505 },
506 };
507
508 GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples =
509 LerpHackKernelSamples(kernel_samples);
510 EXPECT_EQ(fast_kernel_samples.sample_count, 3);
511
512 GaussianBlurPipeline::FragmentShader::KernelSample* samples =
513 kernel_samples.samples;
514 GaussianBlurPipeline::FragmentShader::KernelSample* fast_samples =
515 fast_kernel_samples.samples;
516
517 //////////////////////////////////////////////////////////////////////////////
518 // Check output kernel.
519
520 EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.x, -1.3333333);
521 EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.y, 0);
522 EXPECT_FLOAT_EQ(fast_samples[0].coefficient, 0.3);
523 EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.x, 0);
524 EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.y, 0);
525 EXPECT_FLOAT_EQ(fast_samples[1].coefficient, 0.4);
526 EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.x, 1.3333333);
527 EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.y, 0);
528 EXPECT_FLOAT_EQ(fast_samples[2].coefficient, 0.3);
529
530 //////////////////////////////////////////////////////////////////////////////
531 // Check output of fast kernel versus original kernel.
532
533 Scalar data[5] = {0.25, 0.5, 0.5, 1.0, 0.2};
534 Scalar original_output =
535 samples[0].coefficient * data[0] + samples[1].coefficient * data[1] +
536 samples[2].coefficient * data[2] + samples[3].coefficient * data[3] +
537 samples[4].coefficient * data[4];
538
539 auto lerp = [](const Point& point, Scalar left, Scalar right) {
540 Scalar int_part;
541 Scalar fract = fabsf(modf(point.x, &int_part));
542 if (point.x < 0) {
543 return left * fract + right * (1.0 - fract);
544 } else {
545 return left * (1.0 - fract) + right * fract;
546 }
547 };
548 Scalar fast_output =
549 /*1st*/ lerp(fast_samples[0].uv_offset, data[0], data[1]) *
550 fast_samples[0].coefficient +
551 /*2nd*/ data[2] * fast_samples[1].coefficient +
552 /*3rd*/ lerp(fast_samples[2].uv_offset, data[3], data[4]) *
553 fast_samples[2].coefficient;
554
555 EXPECT_NEAR(original_output, fast_output, 0.01);
556}
static SkPoint lerp(const SkPoint &a, const SkPoint &b, float T)

◆ TEST() [144/399]

impeller::testing::TEST ( GeometryTest  ,
BlendModeToString   
)

Definition at line 1597 of file geometry_unittests.cc.

1597 {
1598 using BlendT = std::underlying_type_t<BlendMode>;
1599 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLast); i++) {
1600 auto mode = static_cast<BlendMode>(i);
1601 auto result = BlendModeToString(mode);
1603 }
1604}
#define _BLEND_MODE_NAME_CHECK(blend_mode)
const char * BlendModeToString(BlendMode blend_mode)
Definition color.cc:47
BlendMode
Definition color.h:59

◆ TEST() [145/399]

impeller::testing::TEST ( GeometryTest  ,
CanConvertBetweenDegressAndRadians   
)

Definition at line 1606 of file geometry_unittests.cc.

1606 {
1607 {
1608 auto deg = Degrees{90.0};
1609 Radians rad = deg;
1610 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1611 }
1612}
Scalar radians
Definition scalar.h:39

◆ TEST() [146/399]

impeller::testing::TEST ( GeometryTest  ,
CanConvertTTypesExplicitly   
)

Definition at line 607 of file geometry_unittests.cc.

607 {
608 {
609 Point p1(1.0, 2.0);
610 IPoint p2 = static_cast<IPoint>(p1);
611 ASSERT_EQ(p2.x, 1u);
612 ASSERT_EQ(p2.y, 2u);
613 }
614
615 {
616 Size s1(1.0, 2.0);
617 ISize s2 = static_cast<ISize>(s1);
618 ASSERT_EQ(s2.width, 1u);
619 ASSERT_EQ(s2.height, 2u);
620 }
621
622 {
623 Size s1(1.0, 2.0);
624 Point p1 = static_cast<Point>(s1);
625 ASSERT_EQ(p1.x, 1u);
626 ASSERT_EQ(p1.y, 2u);
627 }
628}
Type height
Definition size.h:23
Type width
Definition size.h:22

◆ TEST() [147/399]

impeller::testing::TEST ( GeometryTest  ,
CanGenerateMipCounts   
)

Definition at line 594 of file geometry_unittests.cc.

594 {
595 ASSERT_EQ((Size{128, 128}.MipCount()), 7u);
596 ASSERT_EQ((Size{128, 256}.MipCount()), 8u);
597 ASSERT_EQ((Size{128, 130}.MipCount()), 8u);
598 ASSERT_EQ((Size{128, 257}.MipCount()), 9u);
599 ASSERT_EQ((Size{257, 128}.MipCount()), 9u);
600 ASSERT_EQ((Size{128, 0}.MipCount()), 1u);
601 ASSERT_EQ((Size{128, -25}.MipCount()), 1u);
602 ASSERT_EQ((Size{-128, 25}.MipCount()), 1u);
603 ASSERT_EQ((Size{1, 1}.MipCount()), 1u);
604 ASSERT_EQ((Size{0, 0}.MipCount()), 1u);
605}
constexpr size_t MipCount() const
Definition size.h:115

◆ TEST() [148/399]

impeller::testing::TEST ( GeometryTest  ,
CanPerformAlgebraicPointOps   
)

Definition at line 630 of file geometry_unittests.cc.

630 {
631 {
632 IPoint p1(1, 2);
633 IPoint p2 = p1 + IPoint(1, 2);
634 ASSERT_EQ(p2.x, 2u);
635 ASSERT_EQ(p2.y, 4u);
636 }
637
638 {
639 IPoint p1(3, 6);
640 IPoint p2 = p1 - IPoint(1, 2);
641 ASSERT_EQ(p2.x, 2u);
642 ASSERT_EQ(p2.y, 4u);
643 }
644
645 {
646 IPoint p1(1, 2);
647 IPoint p2 = p1 * IPoint(2, 3);
648 ASSERT_EQ(p2.x, 2u);
649 ASSERT_EQ(p2.y, 6u);
650 }
651
652 {
653 IPoint p1(2, 6);
654 IPoint p2 = p1 / IPoint(2, 3);
655 ASSERT_EQ(p2.x, 1u);
656 ASSERT_EQ(p2.y, 2u);
657 }
658}
TPoint< int64_t > IPoint
Definition point.h:317

◆ TEST() [149/399]

impeller::testing::TEST ( GeometryTest  ,
CanPerformAlgebraicPointOpsWithArithmeticTypes   
)

Definition at line 660 of file geometry_unittests.cc.

660 {
661 // LHS
662 {
663 IPoint p1(1, 2);
664 IPoint p2 = p1 * 2.0f;
665 ASSERT_EQ(p2.x, 2u);
666 ASSERT_EQ(p2.y, 4u);
667 }
668
669 {
670 IPoint p1(2, 6);
671 IPoint p2 = p1 / 2.0f;
672 ASSERT_EQ(p2.x, 1u);
673 ASSERT_EQ(p2.y, 3u);
674 }
675
676 // RHS
677 {
678 IPoint p1(1, 2);
679 IPoint p2 = 2.0f * p1;
680 ASSERT_EQ(p2.x, 2u);
681 ASSERT_EQ(p2.y, 4u);
682 }
683
684 {
685 IPoint p1(2, 6);
686 IPoint p2 = 12.0f / p1;
687 ASSERT_EQ(p2.x, 6u);
688 ASSERT_EQ(p2.y, 2u);
689 }
690}

◆ TEST() [150/399]

impeller::testing::TEST ( GeometryTest  ,
CanPerformAlgebraicVector3Ops   
)

Definition at line 1164 of file geometry_unittests.cc.

1164 {
1165 {
1166 Vector3 p1(1, 2, 3);
1167 Vector3 p2 = p1 + Vector3(1, 2, 3);
1168 ASSERT_EQ(p2.x, 2u);
1169 ASSERT_EQ(p2.y, 4u);
1170 ASSERT_EQ(p2.z, 6u);
1171 }
1172
1173 {
1174 Vector3 p1(3, 6, 9);
1175 Vector3 p2 = p1 - Vector3(1, 2, 3);
1176 ASSERT_EQ(p2.x, 2u);
1177 ASSERT_EQ(p2.y, 4u);
1178 ASSERT_EQ(p2.z, 6u);
1179 }
1180
1181 {
1182 Vector3 p1(1, 2, 3);
1183 Vector3 p2 = p1 * Vector3(2, 3, 4);
1184 ASSERT_EQ(p2.x, 2u);
1185 ASSERT_EQ(p2.y, 6u);
1186 ASSERT_EQ(p2.z, 12u);
1187 }
1188
1189 {
1190 Vector3 p1(2, 6, 12);
1191 Vector3 p2 = p1 / Vector3(2, 3, 4);
1192 ASSERT_EQ(p2.x, 1u);
1193 ASSERT_EQ(p2.y, 2u);
1194 ASSERT_EQ(p2.z, 3u);
1195 }
1196}

◆ TEST() [151/399]

impeller::testing::TEST ( GeometryTest  ,
CanPerformAlgebraicVector3OpsWithArithmeticTypes   
)

Definition at line 1198 of file geometry_unittests.cc.

1198 {
1199 // LHS
1200 {
1201 Vector3 p1(1, 2, 3);
1202 Vector3 p2 = p1 + 2.0f;
1203 ASSERT_EQ(p2.x, 3);
1204 ASSERT_EQ(p2.y, 4);
1205 ASSERT_EQ(p2.z, 5);
1206 }
1207
1208 {
1209 Vector3 p1(1, 2, 3);
1210 Vector3 p2 = p1 - 2.0f;
1211 ASSERT_EQ(p2.x, -1);
1212 ASSERT_EQ(p2.y, 0);
1213 ASSERT_EQ(p2.z, 1);
1214 }
1215
1216 {
1217 Vector3 p1(1, 2, 3);
1218 Vector3 p2 = p1 * 2.0f;
1219 ASSERT_EQ(p2.x, 2);
1220 ASSERT_EQ(p2.y, 4);
1221 ASSERT_EQ(p2.z, 6);
1222 }
1223
1224 {
1225 Vector3 p1(2, 6, 12);
1226 Vector3 p2 = p1 / 2.0f;
1227 ASSERT_EQ(p2.x, 1);
1228 ASSERT_EQ(p2.y, 3);
1229 ASSERT_EQ(p2.z, 6);
1230 }
1231
1232 // RHS
1233 {
1234 Vector3 p1(1, 2, 3);
1235 Vector3 p2 = 2.0f + p1;
1236 ASSERT_EQ(p2.x, 3);
1237 ASSERT_EQ(p2.y, 4);
1238 ASSERT_EQ(p2.z, 5);
1239 }
1240
1241 {
1242 Vector3 p1(1, 2, 3);
1243 Vector3 p2 = 2.0f - p1;
1244 ASSERT_EQ(p2.x, 1);
1245 ASSERT_EQ(p2.y, 0);
1246 ASSERT_EQ(p2.z, -1);
1247 }
1248
1249 {
1250 Vector3 p1(1, 2, 3);
1251 Vector3 p2 = 2.0f * p1;
1252 ASSERT_EQ(p2.x, 2);
1253 ASSERT_EQ(p2.y, 4);
1254 ASSERT_EQ(p2.z, 6);
1255 }
1256
1257 {
1258 Vector3 p1(2, 6, 12);
1259 Vector3 p2 = 12.0f / p1;
1260 ASSERT_EQ(p2.x, 6);
1261 ASSERT_EQ(p2.y, 2);
1262 ASSERT_EQ(p2.z, 1);
1263 }
1264}

◆ TEST() [152/399]

impeller::testing::TEST ( GeometryTest  ,
CanUsePointAssignmentOperators   
)

Definition at line 812 of file geometry_unittests.cc.

812 {
813 // Point on RHS
814 {
815 IPoint p(1, 2);
816 p += IPoint(1, 2);
817 ASSERT_EQ(p.x, 2u);
818 ASSERT_EQ(p.y, 4u);
819 }
820
821 {
822 IPoint p(3, 6);
823 p -= IPoint(1, 2);
824 ASSERT_EQ(p.x, 2u);
825 ASSERT_EQ(p.y, 4u);
826 }
827
828 {
829 IPoint p(1, 2);
830 p *= IPoint(2, 3);
831 ASSERT_EQ(p.x, 2u);
832 ASSERT_EQ(p.y, 6u);
833 }
834
835 {
836 IPoint p(2, 6);
837 p /= IPoint(2, 3);
838 ASSERT_EQ(p.x, 1u);
839 ASSERT_EQ(p.y, 2u);
840 }
841
842 // Size on RHS
843 {
844 IPoint p(1, 2);
845 p += ISize(1, 2);
846 ASSERT_EQ(p.x, 2u);
847 ASSERT_EQ(p.y, 4u);
848 }
849
850 {
851 IPoint p(3, 6);
852 p -= ISize(1, 2);
853 ASSERT_EQ(p.x, 2u);
854 ASSERT_EQ(p.y, 4u);
855 }
856
857 {
858 IPoint p(1, 2);
859 p *= ISize(2, 3);
860 ASSERT_EQ(p.x, 2u);
861 ASSERT_EQ(p.y, 6u);
862 }
863
864 {
865 IPoint p(2, 6);
866 p /= ISize(2, 3);
867 ASSERT_EQ(p.x, 1u);
868 ASSERT_EQ(p.y, 2u);
869 }
870
871 // Arithmetic type on RHS
872 {
873 IPoint p(1, 2);
874 p *= 3;
875 ASSERT_EQ(p.x, 3u);
876 ASSERT_EQ(p.y, 6u);
877 }
878
879 {
880 IPoint p(3, 6);
881 p /= 3;
882 ASSERT_EQ(p.x, 1u);
883 ASSERT_EQ(p.y, 2u);
884 }
885}
TSize< int64_t > ISize
Definition size.h:138

◆ TEST() [153/399]

impeller::testing::TEST ( GeometryTest  ,
CanUseVector3AssignmentOperators   
)

Definition at line 1114 of file geometry_unittests.cc.

1114 {
1115 {
1116 Vector3 p(1, 2, 4);
1117 p += Vector3(1, 2, 4);
1118 ASSERT_EQ(p.x, 2u);
1119 ASSERT_EQ(p.y, 4u);
1120 ASSERT_EQ(p.z, 8u);
1121 }
1122
1123 {
1124 Vector3 p(3, 6, 8);
1125 p -= Vector3(1, 2, 3);
1126 ASSERT_EQ(p.x, 2u);
1127 ASSERT_EQ(p.y, 4u);
1128 ASSERT_EQ(p.z, 5u);
1129 }
1130
1131 {
1132 Vector3 p(1, 2, 3);
1133 p *= Vector3(2, 3, 4);
1134 ASSERT_EQ(p.x, 2u);
1135 ASSERT_EQ(p.y, 6u);
1136 ASSERT_EQ(p.z, 12u);
1137 }
1138
1139 {
1140 Vector3 p(1, 2, 3);
1141 p *= 2;
1142 ASSERT_EQ(p.x, 2u);
1143 ASSERT_EQ(p.y, 4u);
1144 ASSERT_EQ(p.z, 6u);
1145 }
1146
1147 {
1148 Vector3 p(2, 6, 12);
1149 p /= Vector3(2, 3, 4);
1150 ASSERT_EQ(p.x, 1u);
1151 ASSERT_EQ(p.y, 2u);
1152 ASSERT_EQ(p.z, 3u);
1153 }
1154
1155 {
1156 Vector3 p(2, 6, 12);
1157 p /= 2;
1158 ASSERT_EQ(p.x, 1u);
1159 ASSERT_EQ(p.y, 3u);
1160 ASSERT_EQ(p.z, 6u);
1161 }
1162}

◆ TEST() [154/399]

impeller::testing::TEST ( GeometryTest  ,
ColorApplyColorMatrix   
)

Definition at line 1371 of file geometry_unittests.cc.

1371 {
1372 {
1373 ColorMatrix color_matrix = {
1374 1, 1, 1, 1, 1, //
1375 1, 1, 1, 1, 1, //
1376 1, 1, 1, 1, 1, //
1377 1, 1, 1, 1, 1, //
1378 };
1379 auto result = Color::White().ApplyColorMatrix(color_matrix);
1380 auto expected = Color(1, 1, 1, 1);
1381 ASSERT_COLOR_NEAR(result, expected);
1382 }
1383
1384 {
1385 ColorMatrix color_matrix = {
1386 0.1, 0, 0, 0, 0.01, //
1387 0, 0.2, 0, 0, 0.02, //
1388 0, 0, 0.3, 0, 0.03, //
1389 0, 0, 0, 0.4, 0.04, //
1390 };
1391 auto result = Color::White().ApplyColorMatrix(color_matrix);
1392 auto expected = Color(0.11, 0.22, 0.33, 0.44);
1393 ASSERT_COLOR_NEAR(result, expected);
1394 }
1395}
#define ASSERT_COLOR_NEAR(a, b)

◆ TEST() [155/399]

impeller::testing::TEST ( GeometryTest  ,
ColorBlendReturnsExpectedResults   
)

Definition at line 1580 of file geometry_unittests.cc.

1580 {
1581 Color dst = ColorBlendTestData::kDestinationColor;
1582 for (size_t source_i = 0;
1583 source_i < sizeof(ColorBlendTestData::kSourceColors) / sizeof(Color);
1584 source_i++) {
1585 Color src = ColorBlendTestData::kSourceColors[source_i];
1586
1587 Color expected;
1589 }
1590}
#define _BLEND_MODE_RESULT_CHECK(blend_mode)

◆ TEST() [156/399]

impeller::testing::TEST ( GeometryTest  ,
ColorClamp01   
)

Definition at line 1331 of file geometry_unittests.cc.

1331 {
1332 {
1333 Color result = Color(0.5, 0.5, 0.5, 0.5).Clamp01();
1334 Color expected = Color(0.5, 0.5, 0.5, 0.5);
1335 ASSERT_COLOR_NEAR(result, expected);
1336 }
1337
1338 {
1339 Color result = Color(-1, -1, -1, -1).Clamp01();
1340 Color expected = Color(0, 0, 0, 0);
1341 ASSERT_COLOR_NEAR(result, expected);
1342 }
1343
1344 {
1345 Color result = Color(2, 2, 2, 2).Clamp01();
1346 Color expected = Color(1, 1, 1, 1);
1347 ASSERT_COLOR_NEAR(result, expected);
1348 }
1349}
constexpr Color Clamp01() const
Definition color.h:238

◆ TEST() [157/399]

impeller::testing::TEST ( GeometryTest  ,
ColorLerp   
)

Definition at line 1309 of file geometry_unittests.cc.

1309 {
1310 {
1311 Color a(0.0, 0.0, 0.0, 0.0);
1312 Color b(1.0, 1.0, 1.0, 1.0);
1313
1314 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.5, 0.5, 0.5, 0.5));
1315 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1316 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1317 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.2, 0.2, 0.2, 0.2));
1318 }
1319
1320 {
1321 Color a(0.2, 0.4, 1.0, 0.5);
1322 Color b(0.4, 1.0, 0.2, 0.3);
1323
1324 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.3, 0.7, 0.6, 0.4));
1325 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1326 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1327 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.24, 0.52, 0.84, 0.46));
1328 }
1329}
struct MyStruct a[10]

◆ TEST() [158/399]

impeller::testing::TEST ( GeometryTest  ,
ColorLinearToSRGB   
)

Definition at line 1397 of file geometry_unittests.cc.

1397 {
1398 {
1399 auto result = Color::White().LinearToSRGB();
1400 auto expected = Color(1, 1, 1, 1);
1401 ASSERT_COLOR_NEAR(result, expected);
1402 }
1403
1404 {
1405 auto result = Color::BlackTransparent().LinearToSRGB();
1406 auto expected = Color(0, 0, 0, 0);
1407 ASSERT_COLOR_NEAR(result, expected);
1408 }
1409
1410 {
1411 auto result = Color(0.2, 0.4, 0.6, 0.8).LinearToSRGB();
1412 auto expected = Color(0.484529, 0.665185, 0.797738, 0.8);
1413 ASSERT_COLOR_NEAR(result, expected);
1414 }
1415}

◆ TEST() [159/399]

impeller::testing::TEST ( GeometryTest  ,
ColorMakeRGBA8   
)

Definition at line 1351 of file geometry_unittests.cc.

1351 {
1352 {
1353 Color a = Color::MakeRGBA8(0, 0, 0, 0);
1354 Color b = Color::BlackTransparent();
1356 }
1357
1358 {
1359 Color a = Color::MakeRGBA8(255, 255, 255, 255);
1360 Color b = Color::White();
1362 }
1363
1364 {
1365 Color a = Color::MakeRGBA8(63, 127, 191, 127);
1366 Color b(0.247059, 0.498039, 0.74902, 0.498039);
1368 }
1369}

◆ TEST() [160/399]

impeller::testing::TEST ( GeometryTest  ,
ColorPremultiply   
)

Definition at line 1266 of file geometry_unittests.cc.

1266 {
1267 {
1268 Color a(1.0, 0.5, 0.2, 0.5);
1269 Color premultiplied = a.Premultiply();
1270 Color expected = Color(0.5, 0.25, 0.1, 0.5);
1271 ASSERT_COLOR_NEAR(premultiplied, expected);
1272 }
1273
1274 {
1275 Color a(0.5, 0.25, 0.1, 0.5);
1276 Color unpremultiplied = a.Unpremultiply();
1277 Color expected = Color(1.0, 0.5, 0.2, 0.5);
1278 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1279 }
1280
1281 {
1282 Color a(0.5, 0.25, 0.1, 0.0);
1283 Color unpremultiplied = a.Unpremultiply();
1284 Color expected = Color(0.0, 0.0, 0.0, 0.0);
1285 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1286 }
1287}

◆ TEST() [161/399]

impeller::testing::TEST ( GeometryTest  ,
ColorPrinting   
)

Definition at line 1689 of file geometry_unittests.cc.

1689 {
1690 {
1691 std::stringstream stream;
1692 Color m;
1693 stream << m;
1694 ASSERT_EQ(stream.str(), "(0, 0, 0, 0)");
1695 }
1696
1697 {
1698 std::stringstream stream;
1699 Color m(1, 2, 3, 4);
1700 stream << m;
1701 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1702 }
1703}

◆ TEST() [162/399]

impeller::testing::TEST ( GeometryTest  ,
ColorR8G8B8A8   
)

Definition at line 1289 of file geometry_unittests.cc.

1289 {
1290 {
1291 Color a(1.0, 0.5, 0.2, 0.5);
1292 std::array<uint8_t, 4> expected = {255, 128, 51, 128};
1293 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1294 }
1295
1296 {
1297 Color a(0.0, 0.0, 0.0, 0.0);
1298 std::array<uint8_t, 4> expected = {0, 0, 0, 0};
1299 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1300 }
1301
1302 {
1303 Color a(1.0, 1.0, 1.0, 1.0);
1304 std::array<uint8_t, 4> expected = {255, 255, 255, 255};
1305 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1306 }
1307}
#define ASSERT_ARRAY_4_NEAR(a, b)

◆ TEST() [163/399]

impeller::testing::TEST ( GeometryTest  ,
ColorSRGBToLinear   
)

Definition at line 1417 of file geometry_unittests.cc.

1417 {
1418 {
1419 auto result = Color::White().SRGBToLinear();
1420 auto expected = Color(1, 1, 1, 1);
1421 ASSERT_COLOR_NEAR(result, expected);
1422 }
1423
1424 {
1425 auto result = Color::BlackTransparent().SRGBToLinear();
1426 auto expected = Color(0, 0, 0, 0);
1427 ASSERT_COLOR_NEAR(result, expected);
1428 }
1429
1430 {
1431 auto result = Color(0.2, 0.4, 0.6, 0.8).SRGBToLinear();
1432 auto expected = Color(0.0331048, 0.132868, 0.318547, 0.8);
1433 ASSERT_COLOR_NEAR(result, expected);
1434 }
1435}

◆ TEST() [164/399]

impeller::testing::TEST ( GeometryTest  ,
DeterminantTest   
)

Definition at line 120 of file geometry_unittests.cc.

120 {
121 auto matrix = Matrix{3, 4, 14, 155, 2, 1, 3, 4, 2, 3, 2, 1, 1, 2, 4, 2};
122 ASSERT_EQ(matrix.GetDeterminant(), -1889);
123}

◆ TEST() [165/399]

impeller::testing::TEST ( GeometryTest  ,
Gradient   
)

Definition at line 1711 of file geometry_unittests.cc.

1711 {
1712 {
1713 // Simple 2 color gradient produces color buffer containing exactly those
1714 // values.
1715 std::vector<Color> colors = {Color::Red(), Color::Blue()};
1716 std::vector<Scalar> stops = {0.0, 1.0};
1717
1718 auto gradient = CreateGradientBuffer(colors, stops);
1719
1720 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1721 ASSERT_EQ(gradient.texture_size, 2u);
1722 }
1723
1724 {
1725 // Gradient with duplicate stops does not create an empty texture.
1726 std::vector<Color> colors = {Color::Red(), Color::Yellow(), Color::Black(),
1727 Color::Blue()};
1728 std::vector<Scalar> stops = {0.0, 0.25, 0.25, 1.0};
1729
1730 auto gradient = CreateGradientBuffer(colors, stops);
1731 ASSERT_EQ(gradient.texture_size, 5u);
1732 }
1733
1734 {
1735 // Simple N color gradient produces color buffer containing exactly those
1736 // values.
1737 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green(),
1738 Color::White()};
1739 std::vector<Scalar> stops = {0.0, 0.33, 0.66, 1.0};
1740
1741 auto gradient = CreateGradientBuffer(colors, stops);
1742
1743 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1744 ASSERT_EQ(gradient.texture_size, 4u);
1745 }
1746
1747 {
1748 // Gradient with color stops will lerp and scale buffer.
1749 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green()};
1750 std::vector<Scalar> stops = {0.0, 0.25, 1.0};
1751
1752 auto gradient = CreateGradientBuffer(colors, stops);
1753
1754 std::vector<Color> lerped_colors = {
1755 Color::Red(),
1756 Color::Blue(),
1757 Color::Lerp(Color::Blue(), Color::Green(), 0.3333),
1758 Color::Lerp(Color::Blue(), Color::Green(), 0.6666),
1759 Color::Green(),
1760 };
1761 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, lerped_colors);
1762 ASSERT_EQ(gradient.texture_size, 5u);
1763 }
1764
1765 {
1766 // Gradient size is capped at 1024.
1767 std::vector<Color> colors = {};
1768 std::vector<Scalar> stops = {};
1769 for (auto i = 0u; i < 1025; i++) {
1770 colors.push_back(Color::Blue());
1771 stops.push_back(i / 1025.0);
1772 }
1773
1774 auto gradient = CreateGradientBuffer(colors, stops);
1775
1776 ASSERT_EQ(gradient.texture_size, 1024u);
1777 ASSERT_EQ(gradient.color_bytes.size(), 1024u * 4);
1778 }
1779}
#define ASSERT_COLOR_BUFFER_NEAR(a, b)
PODArray< SkColor > colors
Definition SkRecords.h:276
GradientData CreateGradientBuffer(const std::vector< Color > &colors, const std::vector< Scalar > &stops)
Populate a vector with the interpolated color bytes for the linear gradient described by colors and s...
Definition gradient.cc:20

◆ TEST() [166/399]

impeller::testing::TEST ( GeometryTest  ,
HalfConversions   
)

Definition at line 1781 of file geometry_unittests.cc.

1781 {
1782#if defined(FML_OS_MACOSX) || defined(FML_OS_IOS) || \
1783 defined(FML_OS_IOS_SIMULATOR)
1784 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
1785 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
1786 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
1787 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
1788
1789 // 65504 is the largest possible half.
1790 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
1791 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
1792
1793 // Colors
1794 ASSERT_EQ(HalfVector4(Color::Red()),
1795 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
1796 ASSERT_EQ(HalfVector4(Color::Green()),
1797 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
1798 ASSERT_EQ(HalfVector4(Color::Blue()),
1799 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
1800 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
1801 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
1802
1803 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
1804 HalfVector3(4.0f16, 6.0f16, -1.0f16));
1805 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
1806
1807 ASSERT_EQ(Half(0.5f), Half(0.5f16));
1808 ASSERT_EQ(Half(0.5), Half(0.5f16));
1809 ASSERT_EQ(Half(5), Half(5.0f16));
1810#else
1811 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
1812 "only used on Apple platforms.";
1813#endif // FML_OS_MACOSX || FML_OS_IOS || FML_OS_IOS_SIMULATOR
1814}
constexpr InternalHalf ScalarToHalf(Scalar f)
Convert a scalar to a half precision float.
Definition half.h:32
A storage only class for half precision floating point vector 2.
Definition half.h:129
A storage only class for half precision floating point vector 3.
Definition half.h:101
A storage only class for half precision floating point vector 4.
Definition half.h:60
A storage only class for half precision floating point.
Definition half.h:41

◆ TEST() [167/399]

impeller::testing::TEST ( GeometryTest  ,
InvertMatrix   
)

Definition at line 125 of file geometry_unittests.cc.

125 {
126 auto inverted = Matrix{10, -9, -12, 8, //
127 7, -12, 11, 22, //
128 -10, 10, 3, 6, //
129 -2, 22, 2, 1}
130 .Invert();
131
132 auto result = Matrix{
133 438.0 / 85123.0, 1751.0 / 85123.0, -7783.0 / 85123.0, 4672.0 / 85123.0,
134 393.0 / 85123.0, -178.0 / 85123.0, -570.0 / 85123.0, 4192 / 85123.0,
135 -5230.0 / 85123.0, 2802.0 / 85123.0, -3461.0 / 85123.0, 962.0 / 85123.0,
136 2690.0 / 85123.0, 1814.0 / 85123.0, 3896.0 / 85123.0, 319.0 / 85123.0};
137
138 ASSERT_MATRIX_NEAR(inverted, result);
139}
Matrix Invert() const
Definition matrix.cc:97

◆ TEST() [168/399]

impeller::testing::TEST ( GeometryTest  ,
InvertMultMatrix   
)

Definition at line 78 of file geometry_unittests.cc.

78 {
79 {
80 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
81 auto invert = rotation.Invert();
82 // clang-format off
83 auto expect = Matrix{k1OverSqrt2, -k1OverSqrt2, 0, 0,
84 k1OverSqrt2, k1OverSqrt2, 0, 0,
85 0, 0, 1, 0,
86 0, 0, 0, 1};
87 // clang-format on
89 }
90 {
91 auto scale = Matrix::MakeScale(Vector2{2, 4});
92 auto invert = scale.Invert();
93 auto expect = Matrix{0.5, 0, 0, 0, //
94 0, 0.25, 0, 0, //
95 0, 0, 1, 0, //
96 0, 0, 0, 1};
98 }
99}
gboolean invert

◆ TEST() [169/399]

impeller::testing::TEST ( GeometryTest  ,
MakeColumn   
)

Definition at line 39 of file geometry_unittests.cc.

39 {
40 auto matrix = Matrix::MakeColumn(1, 2, 3, 4, //
41 5, 6, 7, 8, //
42 9, 10, 11, 12, //
43 13, 14, 15, 16);
44
45 auto expect = Matrix{1, 2, 3, 4, //
46 5, 6, 7, 8, //
47 9, 10, 11, 12, //
48 13, 14, 15, 16};
49
50 ASSERT_TRUE(matrix == expect);
51}

◆ TEST() [170/399]

impeller::testing::TEST ( GeometryTest  ,
MakeRow   
)

Definition at line 53 of file geometry_unittests.cc.

53 {
54 auto matrix = Matrix::MakeRow(1, 2, 3, 4, //
55 5, 6, 7, 8, //
56 9, 10, 11, 12, //
57 13, 14, 15, 16);
58
59 auto expect = Matrix{1, 5, 9, 13, //
60 2, 6, 10, 14, //
61 3, 7, 11, 15, //
62 4, 8, 12, 16};
63
64 ASSERT_TRUE(matrix == expect);
65}

◆ TEST() [171/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixBasis   
)

Definition at line 101 of file geometry_unittests.cc.

101 {
102 auto matrix = Matrix{1, 2, 3, 4, //
103 5, 6, 7, 8, //
104 9, 10, 11, 12, //
105 13, 14, 15, 16};
106 auto basis = matrix.Basis();
107 auto expect = Matrix{1, 2, 3, 0, //
108 5, 6, 7, 0, //
109 9, 10, 11, 0, //
110 0, 0, 0, 1};
111 ASSERT_MATRIX_NEAR(basis, expect);
112}

◆ TEST() [172/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixGetBasisVectors   
)

Definition at line 422 of file geometry_unittests.cc.

422 {
423 {
424 auto m = Matrix();
425 Vector3 x = m.GetBasisX();
426 Vector3 y = m.GetBasisY();
427 Vector3 z = m.GetBasisZ();
428 ASSERT_VECTOR3_NEAR(x, Vector3(1, 0, 0));
429 ASSERT_VECTOR3_NEAR(y, Vector3(0, 1, 0));
430 ASSERT_VECTOR3_NEAR(z, Vector3(0, 0, 1));
431 }
432
433 {
434 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
435 Matrix::MakeRotationX(Radians{kPiOver2}) *
436 Matrix::MakeScale(Vector3(2, 3, 4));
437 Vector3 x = m.GetBasisX();
438 Vector3 y = m.GetBasisY();
439 Vector3 z = m.GetBasisZ();
440 ASSERT_VECTOR3_NEAR(x, Vector3(0, 2, 0));
441 ASSERT_VECTOR3_NEAR(y, Vector3(0, 0, 3));
442 ASSERT_VECTOR3_NEAR(z, Vector3(4, 0, 0));
443 }
444}
#define ASSERT_VECTOR3_NEAR(a, b)

◆ TEST() [173/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixGetDirectionScale   
)

Definition at line 446 of file geometry_unittests.cc.

446 {
447 {
448 auto m = Matrix();
449 Scalar result = m.GetDirectionScale(Vector3{1, 0, 0});
450 ASSERT_FLOAT_EQ(result, 1);
451 }
452
453 {
454 auto m = Matrix::MakeRotationX(Degrees{10}) *
455 Matrix::MakeRotationY(Degrees{83}) *
456 Matrix::MakeRotationZ(Degrees{172});
457 Scalar result = m.GetDirectionScale(Vector3{0, 1, 0});
458 ASSERT_FLOAT_EQ(result, 1);
459 }
460
461 {
462 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
463 Matrix::MakeScale(Vector3(3, 4, 5));
464 Scalar result = m.GetDirectionScale(Vector3{2, 0, 0});
465 ASSERT_FLOAT_EQ(result, 8);
466 }
467}
constexpr float kPiOver2
Definition math.h:30

◆ TEST() [174/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixGetMaxBasisLength   
)

Definition at line 332 of file geometry_unittests.cc.

332 {
333 {
334 auto m = Matrix::MakeScale({3, 1, 1});
335 ASSERT_EQ(m.GetMaxBasisLength(), 3);
336
337 m = m * Matrix::MakeSkew(0, 4);
338 ASSERT_EQ(m.GetMaxBasisLength(), 5);
339 }
340
341 {
342 auto m = Matrix::MakeScale({-3, 4, 2});
343 ASSERT_EQ(m.GetMaxBasisLength(), 4);
344 }
345}

◆ TEST() [175/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixGetMaxBasisLengthXY   
)

Definition at line 347 of file geometry_unittests.cc.

347 {
348 {
349 auto m = Matrix::MakeScale({3, 1, 1});
350 ASSERT_EQ(m.GetMaxBasisLengthXY(), 3);
351
352 m = m * Matrix::MakeSkew(0, 4);
353 ASSERT_EQ(m.GetMaxBasisLengthXY(), 5);
354 }
355
356 {
357 auto m = Matrix::MakeScale({-3, 4, 7});
358 ASSERT_EQ(m.GetMaxBasisLengthXY(), 4);
359 }
360
361 {
362 // clang-format off
363 auto m = Matrix::MakeColumn(
364 1.0f, 0.0f, 0.0f, 0.0f,
365 0.0f, 1.0f, 0.0f, 0.0f,
366 4.0f, 0.0f, 1.0f, 0.0f,
367 0.0f, 0.0f, 0.0f, 1.0f
368 );
369 // clang-format on
370 ASSERT_EQ(m.GetMaxBasisLengthXY(), 1.0f);
371 }
372}

◆ TEST() [176/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixLookAt   
)

Definition at line 495 of file geometry_unittests.cc.

495 {
496 {
497 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
498 Vector3(0, 1, 0));
499 auto expected = Matrix{
500 1, 0, 0, 0, //
501 0, 1, 0, 0, //
502 0, 0, 1, 0, //
503 0, 0, 1, 1, //
504 };
505 ASSERT_MATRIX_NEAR(m, expected);
506 }
507
508 // Sideways tilt.
509 {
510 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
511 Vector3(1, 1, 0).Normalize());
512
513 // clang-format off
514 auto expected = Matrix{
515 k1OverSqrt2, k1OverSqrt2, 0, 0,
516 -k1OverSqrt2, k1OverSqrt2, 0, 0,
517 0, 0, 1, 0,
518 0, 0, 1, 1,
519 };
520 // clang-format on
521 ASSERT_MATRIX_NEAR(m, expected);
522 }
523
524 // Half way between +x and -y, yaw 90
525 {
526 auto m =
527 Matrix::MakeLookAt(Vector3(), Vector3(10, -10, 0), Vector3(0, 0, -1));
528
529 // clang-format off
530 auto expected = Matrix{
531 -k1OverSqrt2, 0, k1OverSqrt2, 0,
532 -k1OverSqrt2, 0, -k1OverSqrt2, 0,
533 0, -1, 0, 0,
534 0, 0, 0, 1,
535 };
536 // clang-format on
537 ASSERT_MATRIX_NEAR(m, expected);
538 }
539}
constexpr float k1OverSqrt2
Definition math.h:48

◆ TEST() [177/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixMakeOrthographic   
)

Definition at line 374 of file geometry_unittests.cc.

374 {
375 {
376 auto m = Matrix::MakeOrthographic(Size(100, 200));
377 auto expect = Matrix{
378 0.02, 0, 0, 0, //
379 0, -0.01, 0, 0, //
380 0, 0, 0, 0, //
381 -1, 1, 0.5, 1, //
382 };
383 ASSERT_MATRIX_NEAR(m, expect);
384 }
385
386 {
387 auto m = Matrix::MakeOrthographic(Size(400, 100));
388 auto expect = Matrix{
389 0.005, 0, 0, 0, //
390 0, -0.02, 0, 0, //
391 0, 0, 0, 0, //
392 -1, 1, 0.5, 1, //
393 };
394 ASSERT_MATRIX_NEAR(m, expect);
395 }
396}

◆ TEST() [178/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixMakePerspective   
)

Definition at line 398 of file geometry_unittests.cc.

398 {
399 {
400 auto m = Matrix::MakePerspective(Degrees(60), Size(100, 200), 1, 10);
401 auto expect = Matrix{
402 3.4641, 0, 0, 0, //
403 0, 1.73205, 0, 0, //
404 0, 0, 1.11111, 1, //
405 0, 0, -1.11111, 0, //
406 };
407 ASSERT_MATRIX_NEAR(m, expect);
408 }
409
410 {
411 auto m = Matrix::MakePerspective(Radians(1), 2, 10, 20);
412 auto expect = Matrix{
413 0.915244, 0, 0, 0, //
414 0, 1.83049, 0, 0, //
415 0, 0, 2, 1, //
416 0, 0, -20, 0, //
417 };
418 ASSERT_MATRIX_NEAR(m, expect);
419 }
420}

◆ TEST() [179/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixMakeRotationFromQuaternion   
)

Definition at line 277 of file geometry_unittests.cc.

277 {
278 {
279 auto matrix = Matrix::MakeRotation(Quaternion({1, 0, 0}, kPiOver2));
280 auto expected = Matrix::MakeRotationX(Radians(kPiOver2));
281 ASSERT_MATRIX_NEAR(matrix, expected);
282 }
283
284 {
285 auto matrix = Matrix::MakeRotation(Quaternion({0, 1, 0}, kPiOver2));
286 auto expected = Matrix::MakeRotationY(Radians(kPiOver2));
287 ASSERT_MATRIX_NEAR(matrix, expected);
288 }
289
290 {
291 auto matrix = Matrix::MakeRotation(Quaternion({0, 0, 1}, kPiOver2));
292 auto expected = Matrix::MakeRotationZ(Radians(kPiOver2));
293 ASSERT_MATRIX_NEAR(matrix, expected);
294 }
295}
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258

◆ TEST() [180/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixPrinting   
)

Definition at line 1614 of file geometry_unittests.cc.

1614 {
1615 {
1616 std::stringstream stream;
1617 Matrix m;
1618 stream << m;
1619 ASSERT_EQ(stream.str(), R"((
1620 1.000000, 0.000000, 0.000000, 0.000000,
1621 0.000000, 1.000000, 0.000000, 0.000000,
1622 0.000000, 0.000000, 1.000000, 0.000000,
1623 0.000000, 0.000000, 0.000000, 1.000000,
1624))");
1625 }
1626
1627 {
1628 std::stringstream stream;
1629 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
1630 stream << m;
1631
1632 ASSERT_EQ(stream.str(), R"((
1633 1.000000, 0.000000, 0.000000, 10.000000,
1634 0.000000, 1.000000, 0.000000, 20.000000,
1635 0.000000, 0.000000, 1.000000, 30.000000,
1636 0.000000, 0.000000, 0.000000, 1.000000,
1637))");
1638 }
1639}

◆ TEST() [181/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixTransformDirection   
)

Definition at line 297 of file geometry_unittests.cc.

297 {
298 {
299 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
300 Matrix::MakeRotationZ(Radians{kPiOver2}) *
301 Matrix::MakeScale({2.0, 2.0, 2.0});
302 auto vector = Vector4(10, 20, 30, 2);
303
304 Vector4 result = matrix.TransformDirection(vector);
305 auto expected = Vector4(-40, 20, 60, 2);
306 ASSERT_VECTOR4_NEAR(result, expected);
307 }
308
309 {
310 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
311 Matrix::MakeRotationZ(Radians{kPiOver2}) *
312 Matrix::MakeScale({2.0, 2.0, 2.0});
313 auto vector = Vector3(10, 20, 30);
314
315 Vector3 result = matrix.TransformDirection(vector);
316 auto expected = Vector3(-40, 20, 60);
317 ASSERT_VECTOR3_NEAR(result, expected);
318 }
319
320 {
321 auto matrix = Matrix::MakeTranslation({0, -0.4, 100}) *
322 Matrix::MakeRotationZ(Radians{kPiOver2}) *
323 Matrix::MakeScale({2.0, 2.0, 2.0});
324 auto vector = Point(10, 20);
325
326 Point result = matrix.TransformDirection(vector);
327 auto expected = Point(-40, 20);
328 ASSERT_POINT_NEAR(result, expected);
329 }
330}
#define ASSERT_VECTOR4_NEAR(a, b)
#define ASSERT_POINT_NEAR(a, b)

◆ TEST() [182/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixTranslationScaleOnly   
)

Definition at line 469 of file geometry_unittests.cc.

469 {
470 {
471 auto m = Matrix();
472 bool result = m.IsTranslationScaleOnly();
473 ASSERT_TRUE(result);
474 }
475
476 {
477 auto m = Matrix::MakeScale(Vector3(2, 3, 4));
478 bool result = m.IsTranslationScaleOnly();
479 ASSERT_TRUE(result);
480 }
481
482 {
483 auto m = Matrix::MakeTranslation(Vector3(2, 3, 4));
484 bool result = m.IsTranslationScaleOnly();
485 ASSERT_TRUE(result);
486 }
487
488 {
489 auto m = Matrix::MakeRotationZ(Degrees(10));
490 bool result = m.IsTranslationScaleOnly();
491 ASSERT_FALSE(result);
492 }
493}

◆ TEST() [183/399]

impeller::testing::TEST ( GeometryTest  ,
MatrixVectorMultiplication   
)

Definition at line 212 of file geometry_unittests.cc.

212 {
213 {
214 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
215 Matrix::MakeRotationZ(Radians{kPiOver2}) *
216 Matrix::MakeScale({2.0, 2.0, 2.0});
217 auto vector = Vector4(10, 20, 30, 2);
218
219 Vector4 result = matrix * vector;
220 auto expected = Vector4(160, 220, 260, 2);
221 ASSERT_VECTOR4_NEAR(result, expected);
222 }
223
224 {
225 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
226 Matrix::MakeRotationZ(Radians{kPiOver2}) *
227 Matrix::MakeScale({2.0, 2.0, 2.0});
228 auto vector = Vector3(10, 20, 30);
229
230 Vector3 result = matrix * vector;
231 auto expected = Vector3(60, 120, 160);
232 ASSERT_VECTOR3_NEAR(result, expected);
233 }
234
235 {
236 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
237 Matrix::MakeRotationZ(Radians{kPiOver2}) *
238 Matrix::MakeScale({2.0, 2.0, 2.0});
239 auto vector = Point(10, 20);
240
241 Point result = matrix * vector;
242 auto expected = Point(60, 120);
243 ASSERT_POINT_NEAR(result, expected);
244 }
245
246 // Matrix Vector ops should respect perspective transforms.
247 {
248 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100);
249 auto vector = Vector3(3, 3, -3);
250
251 Vector3 result = matrix * vector;
252 auto expected = Vector3(-1, -1, 1.3468);
253 ASSERT_VECTOR3_NEAR(result, expected);
254 }
255
256 {
257 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100) *
258 Matrix::MakeTranslation(Vector3(0, 0, -3));
259 auto point = Point(3, 3);
260
261 Point result = matrix * point;
262 auto expected = Point(-1, -1);
263 ASSERT_POINT_NEAR(result, expected);
264 }
265
266 // Resolves to 0 on perspective singularity.
267 {
268 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100);
269 auto point = Point(3, 3);
270
271 Point result = matrix * point;
272 auto expected = Point(0, 0);
273 ASSERT_POINT_NEAR(result, expected);
274 }
275}

◆ TEST() [184/399]

impeller::testing::TEST ( GeometryTest  ,
MutliplicationMatrix   
)

Definition at line 114 of file geometry_unittests.cc.

114 {
115 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
116 auto invert = rotation.Invert();
117 ASSERT_MATRIX_NEAR(rotation * invert, Matrix{});
118}

◆ TEST() [185/399]

impeller::testing::TEST ( GeometryTest  ,
PointAbs   
)

Definition at line 952 of file geometry_unittests.cc.

952 {
953 Point a(-1, -2);
954 auto a_abs = a.Abs();
955 auto expected = Point(1, 2);
956 ASSERT_POINT_NEAR(a_abs, expected);
957}

◆ TEST() [186/399]

impeller::testing::TEST ( GeometryTest  ,
PointAngleTo   
)

Definition at line 959 of file geometry_unittests.cc.

959 {
960 // Negative result in the CCW (with up = -Y) direction.
961 {
962 Point a(1, 1);
963 Point b(1, -1);
964 Radians actual = a.AngleTo(b);
965 Radians expected = Radians{-kPi / 2};
966 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
967 }
968
969 // Check the other direction to ensure the result is signed correctly.
970 {
971 Point a(1, -1);
972 Point b(1, 1);
973 Radians actual = a.AngleTo(b);
974 Radians expected = Radians{kPi / 2};
975 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
976 }
977
978 // Differences in magnitude should have no impact on the result.
979 {
980 Point a(100, -100);
981 Point b(0.01, 0.01);
982 Radians actual = a.AngleTo(b);
983 Radians expected = Radians{kPi / 2};
984 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
985 }
986}

◆ TEST() [187/399]

impeller::testing::TEST ( GeometryTest  ,
PointCeil   
)

Definition at line 1051 of file geometry_unittests.cc.

1051 {
1052 Point p(1.5, 2.3);
1053 Point result = p.Ceil();
1054 Point expected(2, 3);
1055 ASSERT_POINT_NEAR(result, expected);
1056}

◆ TEST() [188/399]

impeller::testing::TEST ( GeometryTest  ,
PointCrossProduct   
)

Definition at line 907 of file geometry_unittests.cc.

907 {
908 {
909 Point p(1, 0);
910 Scalar s = p.Cross(Point(-1, 0));
911 ASSERT_FLOAT_EQ(s, 0);
912 }
913
914 {
915 Point p(0, -1);
916 Scalar s = p.Cross(Point(-1, 0));
917 ASSERT_FLOAT_EQ(s, -1);
918 }
919
920 {
921 Point p(1, 2);
922 Scalar s = p.Cross(Point(3, -4));
923 ASSERT_FLOAT_EQ(s, -10);
924 }
925}
struct MyStruct s

◆ TEST() [189/399]

impeller::testing::TEST ( GeometryTest  ,
PointDotProduct   
)

Definition at line 887 of file geometry_unittests.cc.

887 {
888 {
889 Point p(1, 0);
890 Scalar s = p.Dot(Point(-1, 0));
891 ASSERT_FLOAT_EQ(s, -1);
892 }
893
894 {
895 Point p(0, -1);
896 Scalar s = p.Dot(Point(-1, 0));
897 ASSERT_FLOAT_EQ(s, 0);
898 }
899
900 {
901 Point p(1, 2);
902 Scalar s = p.Dot(Point(3, -4));
903 ASSERT_FLOAT_EQ(s, -5);
904 }
905}

◆ TEST() [190/399]

impeller::testing::TEST ( GeometryTest  ,
PointFloor   
)

Definition at line 1030 of file geometry_unittests.cc.

1030 {
1031 Point p(1.5, 2.3);
1032 Point result = p.Floor();
1033 Point expected(1, 2);
1034 ASSERT_POINT_NEAR(result, expected);
1035}

◆ TEST() [191/399]

impeller::testing::TEST ( GeometryTest  ,
PointIntegerCoercesToFloat   
)

Definition at line 692 of file geometry_unittests.cc.

692 {
693 // Integer on LHS, float on RHS
694 {
695 IPoint p1(1, 2);
696 Point p2 = p1 + Point(1, 2);
697 ASSERT_FLOAT_EQ(p2.x, 2u);
698 ASSERT_FLOAT_EQ(p2.y, 4u);
699 }
700
701 {
702 IPoint p1(3, 6);
703 Point p2 = p1 - Point(1, 2);
704 ASSERT_FLOAT_EQ(p2.x, 2u);
705 ASSERT_FLOAT_EQ(p2.y, 4u);
706 }
707
708 {
709 IPoint p1(1, 2);
710 Point p2 = p1 * Point(2, 3);
711 ASSERT_FLOAT_EQ(p2.x, 2u);
712 ASSERT_FLOAT_EQ(p2.y, 6u);
713 }
714
715 {
716 IPoint p1(2, 6);
717 Point p2 = p1 / Point(2, 3);
718 ASSERT_FLOAT_EQ(p2.x, 1u);
719 ASSERT_FLOAT_EQ(p2.y, 2u);
720 }
721
722 // Float on LHS, integer on RHS
723 {
724 Point p1(1, 2);
725 Point p2 = p1 + IPoint(1, 2);
726 ASSERT_FLOAT_EQ(p2.x, 2u);
727 ASSERT_FLOAT_EQ(p2.y, 4u);
728 }
729
730 {
731 Point p1(3, 6);
732 Point p2 = p1 - IPoint(1, 2);
733 ASSERT_FLOAT_EQ(p2.x, 2u);
734 ASSERT_FLOAT_EQ(p2.y, 4u);
735 }
736
737 {
738 Point p1(1, 2);
739 Point p2 = p1 * IPoint(2, 3);
740 ASSERT_FLOAT_EQ(p2.x, 2u);
741 ASSERT_FLOAT_EQ(p2.y, 6u);
742 }
743
744 {
745 Point p1(2, 6);
746 Point p2 = p1 / IPoint(2, 3);
747 ASSERT_FLOAT_EQ(p2.x, 1u);
748 ASSERT_FLOAT_EQ(p2.y, 2u);
749 }
750}

◆ TEST() [192/399]

impeller::testing::TEST ( GeometryTest  ,
PointLerp   
)

Definition at line 1093 of file geometry_unittests.cc.

1093 {
1094 Point p(1, 2);
1095 Point result = p.Lerp({5, 10}, 0.75);
1096 Point expected(4, 8);
1097 ASSERT_POINT_NEAR(result, expected);
1098}

◆ TEST() [193/399]

impeller::testing::TEST ( GeometryTest  ,
PointMax   
)

Definition at line 1009 of file geometry_unittests.cc.

1009 {
1010 Point p(1, 2);
1011 Point result = p.Max({0, 10});
1012 Point expected(1, 10);
1013 ASSERT_POINT_NEAR(result, expected);
1014}

◆ TEST() [194/399]

impeller::testing::TEST ( GeometryTest  ,
PointMin   
)

Definition at line 988 of file geometry_unittests.cc.

988 {
989 Point p(1, 2);
990 Point result = p.Min({0, 10});
991 Point expected(0, 2);
992 ASSERT_POINT_NEAR(result, expected);
993}

◆ TEST() [195/399]

impeller::testing::TEST ( GeometryTest  ,
PointPrinting   
)

Definition at line 1641 of file geometry_unittests.cc.

1641 {
1642 {
1643 std::stringstream stream;
1644 Point m;
1645 stream << m;
1646 ASSERT_EQ(stream.str(), "(0, 0)");
1647 }
1648
1649 {
1650 std::stringstream stream;
1651 Point m(13, 37);
1652 stream << m;
1653 ASSERT_EQ(stream.str(), "(13, 37)");
1654 }
1655}

◆ TEST() [196/399]

impeller::testing::TEST ( GeometryTest  ,
PointReflect   
)

Definition at line 927 of file geometry_unittests.cc.

927 {
928 {
929 Point axis = Point(0, 1);
930 Point a(2, 3);
931 auto reflected = a.Reflect(axis);
932 auto expected = Point(2, -3);
933 ASSERT_POINT_NEAR(reflected, expected);
934 }
935
936 {
937 Point axis = Point(1, 1).Normalize();
938 Point a(1, 0);
939 auto reflected = a.Reflect(axis);
940 auto expected = Point(0, -1);
941 ASSERT_POINT_NEAR(reflected, expected);
942 }
943
944 {
945 Point axis = Point(1, 1).Normalize();
946 Point a(-1, -1);
947 auto reflected = a.Reflect(axis);
948 ASSERT_POINT_NEAR(reflected, -a);
949 }
950}
constexpr TPoint Normalize() const
Definition point.h:208

◆ TEST() [197/399]

impeller::testing::TEST ( GeometryTest  ,
PointRound   
)

Definition at line 1072 of file geometry_unittests.cc.

1072 {
1073 Point p(1.5, 2.3);
1074 Point result = p.Round();
1075 Point expected(2, 2);
1076 ASSERT_POINT_NEAR(result, expected);
1077}

◆ TEST() [198/399]

impeller::testing::TEST ( GeometryTest  ,
QuaternionLerp   
)

Definition at line 541 of file geometry_unittests.cc.

541 {
542 auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0};
543 auto q2 = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
544
545 auto q3 = q1.Slerp(q2, 0.5);
546
547 auto expected = Quaternion{{0.0, 0.0, 1.0}, kPiOver4 / 2.0};
548
549 ASSERT_QUATERNION_NEAR(q3, expected);
550}
#define ASSERT_QUATERNION_NEAR(a, b)
constexpr float kPiOver4
Definition math.h:33

◆ TEST() [199/399]

impeller::testing::TEST ( GeometryTest  ,
QuaternionVectorMultiply   
)

Definition at line 552 of file geometry_unittests.cc.

552 {
553 {
554 Quaternion q({0, 0, 1}, 0);
555 Vector3 v(0, 1, 0);
556
557 Vector3 result = q * v;
558 Vector3 expected(0, 1, 0);
559
560 ASSERT_VECTOR3_NEAR(result, expected);
561 }
562
563 {
564 Quaternion q({0, 0, 1}, k2Pi);
565 Vector3 v(1, 0, 0);
566
567 Vector3 result = q * v;
568 Vector3 expected(1, 0, 0);
569
570 ASSERT_VECTOR3_NEAR(result, expected);
571 }
572
573 {
574 Quaternion q({0, 0, 1}, kPiOver4);
575 Vector3 v(0, 1, 0);
576
577 Vector3 result = q * v;
578 Vector3 expected(-k1OverSqrt2, k1OverSqrt2, 0);
579
580 ASSERT_VECTOR3_NEAR(result, expected);
581 }
582
583 {
584 Quaternion q(Vector3(1, 0, 1).Normalize(), kPi);
585 Vector3 v(0, 0, -1);
586
587 Vector3 result = q * v;
588 Vector3 expected(-1, 0, 0);
589
590 ASSERT_VECTOR3_NEAR(result, expected);
591 }
592}
constexpr float k2Pi
Definition constants.h:29

◆ TEST() [200/399]

impeller::testing::TEST ( GeometryTest  ,
RotationMatrix   
)

Definition at line 67 of file geometry_unittests.cc.

67 {
68 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
69 // clang-format off
70 auto expect = Matrix{k1OverSqrt2, k1OverSqrt2, 0, 0,
71 -k1OverSqrt2, k1OverSqrt2, 0, 0,
72 0, 0, 1, 0,
73 0, 0, 0, 1};
74 // clang-format on
75 ASSERT_MATRIX_NEAR(rotation, expect);
76}

◆ TEST() [201/399]

impeller::testing::TEST ( GeometryTest  ,
ScalarNearlyEqual   
)

Definition at line 30 of file geometry_unittests.cc.

30 {
31 ASSERT_FALSE(ScalarNearlyEqual(0.0021f, 0.001f));
32 ASSERT_TRUE(ScalarNearlyEqual(0.0019f, 0.001f));
33 ASSERT_TRUE(ScalarNearlyEqual(0.002f, 0.001f, 0.0011f));
34 ASSERT_FALSE(ScalarNearlyEqual(0.002f, 0.001f, 0.0009f));
35 ASSERT_TRUE(ScalarNearlyEqual(
36 1.0f, 1.0f + std::numeric_limits<float>::epsilon() * 4));
37}
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition scalar.h:30

◆ TEST() [202/399]

impeller::testing::TEST ( GeometryTest  ,
SizeCoercesToPoint   
)

Definition at line 752 of file geometry_unittests.cc.

752 {
753 // Point on LHS, Size on RHS
754 {
755 IPoint p1(1, 2);
756 IPoint p2 = p1 + ISize(1, 2);
757 ASSERT_EQ(p2.x, 2u);
758 ASSERT_EQ(p2.y, 4u);
759 }
760
761 {
762 IPoint p1(3, 6);
763 IPoint p2 = p1 - ISize(1, 2);
764 ASSERT_EQ(p2.x, 2u);
765 ASSERT_EQ(p2.y, 4u);
766 }
767
768 {
769 IPoint p1(1, 2);
770 IPoint p2 = p1 * ISize(2, 3);
771 ASSERT_EQ(p2.x, 2u);
772 ASSERT_EQ(p2.y, 6u);
773 }
774
775 {
776 IPoint p1(2, 6);
777 IPoint p2 = p1 / ISize(2, 3);
778 ASSERT_EQ(p2.x, 1u);
779 ASSERT_EQ(p2.y, 2u);
780 }
781
782 // Size on LHS, Point on RHS
783 {
784 ISize p1(1, 2);
785 IPoint p2 = p1 + IPoint(1, 2);
786 ASSERT_EQ(p2.x, 2u);
787 ASSERT_EQ(p2.y, 4u);
788 }
789
790 {
791 ISize p1(3, 6);
792 IPoint p2 = p1 - IPoint(1, 2);
793 ASSERT_EQ(p2.x, 2u);
794 ASSERT_EQ(p2.y, 4u);
795 }
796
797 {
798 ISize p1(1, 2);
799 IPoint p2 = p1 * IPoint(2, 3);
800 ASSERT_EQ(p2.x, 2u);
801 ASSERT_EQ(p2.y, 6u);
802 }
803
804 {
805 ISize p1(2, 6);
806 IPoint p2 = p1 / IPoint(2, 3);
807 ASSERT_EQ(p2.x, 1u);
808 ASSERT_EQ(p2.y, 2u);
809 }
810}

◆ TEST() [203/399]

impeller::testing::TEST ( GeometryTest  ,
TestDecomposition   
)

Definition at line 141 of file geometry_unittests.cc.

141 {
142 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
143
144 auto result = rotated.Decompose();
145
146 ASSERT_TRUE(result.has_value());
147
148 MatrixDecomposition res = result.value();
149
150 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
151 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
152}

◆ TEST() [204/399]

impeller::testing::TEST ( GeometryTest  ,
TestDecomposition2   
)

Definition at line 154 of file geometry_unittests.cc.

154 {
155 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
156 auto scaled = Matrix::MakeScale({2.0, 3.0, 1.0});
157 auto translated = Matrix::MakeTranslation({-200, 750, 20});
158
159 auto result = (translated * rotated * scaled).Decompose();
160
161 ASSERT_TRUE(result.has_value());
162
163 MatrixDecomposition res = result.value();
164
165 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
166
167 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
168
169 ASSERT_FLOAT_EQ(res.translation.x, -200);
170 ASSERT_FLOAT_EQ(res.translation.y, 750);
171 ASSERT_FLOAT_EQ(res.translation.z, 20);
172
173 ASSERT_FLOAT_EQ(res.scale.x, 2);
174 ASSERT_FLOAT_EQ(res.scale.y, 3);
175 ASSERT_FLOAT_EQ(res.scale.z, 1);
176}

◆ TEST() [205/399]

impeller::testing::TEST ( GeometryTest  ,
TestRecomposition   
)

Definition at line 178 of file geometry_unittests.cc.

178 {
179 /*
180 * Decomposition.
181 */
182 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
183
184 auto result = rotated.Decompose();
185
186 ASSERT_TRUE(result.has_value());
187
188 MatrixDecomposition res = result.value();
189
190 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
191
192 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
193
194 /*
195 * Recomposition.
196 */
197 ASSERT_MATRIX_NEAR(rotated, Matrix{res});
198}

◆ TEST() [206/399]

impeller::testing::TEST ( GeometryTest  ,
TestRecomposition2   
)

Definition at line 200 of file geometry_unittests.cc.

200 {
201 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
202 Matrix::MakeRotationZ(Radians{kPiOver4}) *
203 Matrix::MakeScale({2.0, 2.0, 2.0});
204
205 auto result = matrix.Decompose();
206
207 ASSERT_TRUE(result.has_value());
208
209 ASSERT_MATRIX_NEAR(matrix, Matrix{result.value()});
210}

◆ TEST() [207/399]

impeller::testing::TEST ( GeometryTest  ,
ToIColor   
)

Definition at line 1705 of file geometry_unittests.cc.

1705 {
1706 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
1707 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
1708 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
1709}

◆ TEST() [208/399]

impeller::testing::TEST ( GeometryTest  ,
Vector3Ceil   
)

Definition at line 1058 of file geometry_unittests.cc.

1058 {
1059 Vector3 p(1.5, 2.3, 3.9);
1060 Vector3 result = p.Ceil();
1061 Vector3 expected(2, 3, 4);
1062 ASSERT_VECTOR3_NEAR(result, expected);
1063}

◆ TEST() [209/399]

impeller::testing::TEST ( GeometryTest  ,
Vector3Floor   
)

Definition at line 1037 of file geometry_unittests.cc.

1037 {
1038 Vector3 p(1.5, 2.3, 3.9);
1039 Vector3 result = p.Floor();
1040 Vector3 expected(1, 2, 3);
1041 ASSERT_VECTOR3_NEAR(result, expected);
1042}

◆ TEST() [210/399]

impeller::testing::TEST ( GeometryTest  ,
Vector3Lerp   
)

Definition at line 1100 of file geometry_unittests.cc.

1100 {
1101 Vector3 p(1, 2, 3);
1102 Vector3 result = p.Lerp({5, 10, 15}, 0.75);
1103 Vector3 expected(4, 8, 12);
1104 ASSERT_VECTOR3_NEAR(result, expected);
1105}

◆ TEST() [211/399]

impeller::testing::TEST ( GeometryTest  ,
Vector3Max   
)

Definition at line 1016 of file geometry_unittests.cc.

1016 {
1017 Vector3 p(1, 2, 3);
1018 Vector3 result = p.Max({0, 10, 2});
1019 Vector3 expected(1, 10, 3);
1020 ASSERT_VECTOR3_NEAR(result, expected);
1021}

◆ TEST() [212/399]

impeller::testing::TEST ( GeometryTest  ,
Vector3Min   
)

Definition at line 995 of file geometry_unittests.cc.

995 {
996 Vector3 p(1, 2, 3);
997 Vector3 result = p.Min({0, 10, 2});
998 Vector3 expected(0, 2, 2);
999 ASSERT_VECTOR3_NEAR(result, expected);
1000}

◆ TEST() [213/399]

impeller::testing::TEST ( GeometryTest  ,
Vector3Printing   
)

Definition at line 1657 of file geometry_unittests.cc.

1657 {
1658 {
1659 std::stringstream stream;
1660 Vector3 m;
1661 stream << m;
1662 ASSERT_EQ(stream.str(), "(0, 0, 0)");
1663 }
1664
1665 {
1666 std::stringstream stream;
1667 Vector3 m(1, 2, 3);
1668 stream << m;
1669 ASSERT_EQ(stream.str(), "(1, 2, 3)");
1670 }
1671}

◆ TEST() [214/399]

impeller::testing::TEST ( GeometryTest  ,
Vector3Round   
)

Definition at line 1079 of file geometry_unittests.cc.

1079 {
1080 Vector3 p(1.5, 2.3, 3.9);
1081 Vector3 result = p.Round();
1082 Vector3 expected(2, 2, 4);
1083 ASSERT_VECTOR3_NEAR(result, expected);
1084}

◆ TEST() [215/399]

impeller::testing::TEST ( GeometryTest  ,
Vector4Ceil   
)

Definition at line 1065 of file geometry_unittests.cc.

1065 {
1066 Vector4 p(1.5, 2.3, 3.9, 4.0);
1067 Vector4 result = p.Ceil();
1068 Vector4 expected(2, 3, 4, 4);
1069 ASSERT_VECTOR4_NEAR(result, expected);
1070}

◆ TEST() [216/399]

impeller::testing::TEST ( GeometryTest  ,
Vector4Floor   
)

Definition at line 1044 of file geometry_unittests.cc.

1044 {
1045 Vector4 p(1.5, 2.3, 3.9, 4.0);
1046 Vector4 result = p.Floor();
1047 Vector4 expected(1, 2, 3, 4);
1048 ASSERT_VECTOR4_NEAR(result, expected);
1049}

◆ TEST() [217/399]

impeller::testing::TEST ( GeometryTest  ,
Vector4Lerp   
)

Definition at line 1107 of file geometry_unittests.cc.

1107 {
1108 Vector4 p(1, 2, 3, 4);
1109 Vector4 result = p.Lerp({5, 10, 15, 20}, 0.75);
1110 Vector4 expected(4, 8, 12, 16);
1111 ASSERT_VECTOR4_NEAR(result, expected);
1112}

◆ TEST() [218/399]

impeller::testing::TEST ( GeometryTest  ,
Vector4Max   
)

Definition at line 1023 of file geometry_unittests.cc.

1023 {
1024 Vector4 p(1, 2, 3, 4);
1025 Vector4 result = p.Max({0, 10, 2, 1});
1026 Vector4 expected(1, 10, 3, 4);
1027 ASSERT_VECTOR4_NEAR(result, expected);
1028}

◆ TEST() [219/399]

impeller::testing::TEST ( GeometryTest  ,
Vector4Min   
)

Definition at line 1002 of file geometry_unittests.cc.

1002 {
1003 Vector4 p(1, 2, 3, 4);
1004 Vector4 result = p.Min({0, 10, 2, 1});
1005 Vector4 expected(0, 2, 2, 1);
1006 ASSERT_VECTOR4_NEAR(result, expected);
1007}

◆ TEST() [220/399]

impeller::testing::TEST ( GeometryTest  ,
Vector4Printing   
)

Definition at line 1673 of file geometry_unittests.cc.

1673 {
1674 {
1675 std::stringstream stream;
1676 Vector4 m;
1677 stream << m;
1678 ASSERT_EQ(stream.str(), "(0, 0, 0, 1)");
1679 }
1680
1681 {
1682 std::stringstream stream;
1683 Vector4 m(1, 2, 3, 4);
1684 stream << m;
1685 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1686 }
1687}

◆ TEST() [221/399]

impeller::testing::TEST ( GeometryTest  ,
Vector4Round   
)

Definition at line 1086 of file geometry_unittests.cc.

1086 {
1087 Vector4 p(1.5, 2.3, 3.9, 4.0);
1088 Vector4 result = p.Round();
1089 Vector4 expected(2, 2, 4, 4);
1090 ASSERT_VECTOR4_NEAR(result, expected);
1091}

◆ TEST() [222/399]

impeller::testing::TEST ( MatrixTest  ,
HasPerspective   
)

Definition at line 45 of file matrix_unittests.cc.

45 {
46 EXPECT_FALSE(Matrix().HasPerspective());
47
48 auto test = [](int index, bool expect) {
49 Matrix matrix;
50 EXPECT_FALSE(matrix.HasPerspective());
51 matrix.m[index] = 0.5f;
52 EXPECT_EQ(matrix.HasPerspective(), expect) << "index: " << index;
53 };
54
55 // clang-format off
56 test( 0, false); test( 1, false); test( 2, false); test( 3, true);
57 test( 4, false); test( 5, false); test( 6, false); test( 7, true);
58 test( 8, false); test( 9, false); test(10, false); test(11, true);
59 test(12, false); test(13, false); test(14, false); test(15, true);
60 // clang-format on
61}

◆ TEST() [223/399]

impeller::testing::TEST ( MatrixTest  ,
HasPerspective2D   
)

Definition at line 27 of file matrix_unittests.cc.

27 {
28 EXPECT_FALSE(Matrix().HasPerspective2D());
29
30 auto test = [](int index, bool expect) {
31 Matrix matrix;
32 EXPECT_FALSE(matrix.HasPerspective2D());
33 matrix.m[index] = 0.5f;
34 EXPECT_EQ(matrix.HasPerspective2D(), expect) << "index: " << index;
35 };
36
37 // clang-format off
38 test( 0, false); test( 1, false); test( 2, false); test( 3, true);
39 test( 4, false); test( 5, false); test( 6, false); test( 7, true);
40 test( 8, false); test( 9, false); test(10, false); test(11, false);
41 test(12, false); test(13, false); test(14, false); test(15, true);
42 // clang-format on
43}

◆ TEST() [224/399]

impeller::testing::TEST ( MatrixTest  ,
IsAligned   
)

Definition at line 96 of file matrix_unittests.cc.

96 {
97 EXPECT_TRUE(Matrix().IsAligned());
98 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned());
99
100 // Begin Legacy tests transferred over from geometry_unittests.cc
101 {
102 auto m = Matrix::MakeTranslation({1, 2, 3});
103 bool result = m.IsAligned();
104 ASSERT_TRUE(result);
105 }
106
107 {
108 auto m = Matrix::MakeRotationZ(Degrees{123});
109 bool result = m.IsAligned();
110 ASSERT_FALSE(result);
111 }
112 // End Legacy tests transferred over from geometry_unittests.cc
113
114 auto test = [](int index, bool expect) {
115 Matrix matrix;
116 EXPECT_TRUE(matrix.IsAligned());
117 matrix.m[index] = 0.5f;
118 EXPECT_EQ(matrix.IsAligned(), expect) << "index: " << index;
119 };
120
121 // clang-format off
122 test( 0, true); test( 1, false); test( 2, false); test( 3, false);
123 test( 4, false); test( 5, true); test( 6, false); test( 7, false);
124 test( 8, false); test( 9, false); test(10, true); test(11, false);
125 test(12, true); test(13, true); test(14, true); test(15, false);
126 // clang-format on
127
128 // True for quadrant rotations from -250 to +250 full circles
129 for (int i = -1000; i < 1000; i++) {
130 Degrees d = Degrees(i * 90);
131 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
132 EXPECT_TRUE(matrix.IsAligned()) << "degrees: " << d.degrees;
133 }
134
135 // False for half degree rotations from -999.5 to +1000.5 degrees
136 for (int i = -1000; i < 1000; i++) {
137 Degrees d = Degrees(i + 0.5f);
138 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
139 EXPECT_FALSE(matrix.IsAligned()) << "degrees: " << d.degrees;
140 }
141}
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19

◆ TEST() [225/399]

impeller::testing::TEST ( MatrixTest  ,
IsAligned2D   
)

Definition at line 63 of file matrix_unittests.cc.

63 {
64 EXPECT_TRUE(Matrix().IsAligned2D());
65 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
66
67 auto test = [](int index, bool expect) {
68 Matrix matrix;
69 EXPECT_TRUE(matrix.IsAligned2D());
70 matrix.m[index] = 0.5f;
71 EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
72 };
73
74 // clang-format off
75 test( 0, true); test( 1, false); test( 2, true); test( 3, false);
76 test( 4, false); test( 5, true); test( 6, true); test( 7, false);
77 test( 8, true); test( 9, true); test(10, true); test(11, true);
78 test(12, true); test(13, true); test(14, true); test(15, false);
79 // clang-format on
80
81 // True for quadrant rotations from -250 to +250 full circles
82 for (int i = -1000; i < 1000; i++) {
83 Degrees d = Degrees(i * 90);
84 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
85 EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
86 }
87
88 // False for half degree rotations from -999.5 to +1000.5 degrees
89 for (int i = -1000; i < 1000; i++) {
90 Degrees d = Degrees(i + 0.5f);
91 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
92 EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
93 }
94}

◆ TEST() [226/399]

impeller::testing::TEST ( MatrixTest  ,
Multiply   
)

Definition at line 14 of file matrix_unittests.cc.

14 {
15 Matrix x(0.0, 0.0, 0.0, 1.0, //
16 1.0, 0.0, 0.0, 1.0, //
17 0.0, 1.0, 0.0, 1.0, //
18 1.0, 1.0, 0.0, 1.0);
19 Matrix translate = Matrix::MakeTranslation({10, 20, 0});
20 Matrix result = translate * x;
21 EXPECT_TRUE(MatrixNear(result, Matrix(10.0, 20.0, 0.0, 1.0, //
22 11.0, 20.0, 0.0, 1.0, //
23 10.0, 21.0, 0.0, 1.0, //
24 11.0, 21.0, 0.0, 1.0)));
25}
inline ::testing::AssertionResult MatrixNear(impeller::Matrix a, impeller::Matrix b)

◆ TEST() [227/399]

impeller::testing::TEST ( MatrixTest  ,
TransformHomogenous   
)

Definition at line 143 of file matrix_unittests.cc.

143 {
144 Matrix matrix = Matrix::MakeColumn(
145 // clang-format off
146 2.0f, 3.0f, 5.0f, 7.0f,
147 11.0f, 13.0f, 17.0f, 19.0f,
148 23.0f, 29.0f, 31.0f, 37.0f,
149 41.0f, 43.0f, 47.0f, 53.0f
150 // clang-format on
151 );
152 EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
153 Vector3(32.0f, 33.0f, 41.0f));
154}

◆ TEST() [228/399]

impeller::testing::TEST ( MockGLES  ,
CanCallUnmockedFunction   
)

Definition at line 38 of file mock_gles_unittests.cc.

38 {
39 auto mock_gles = MockGLES::Init();
40
41 auto& gl = mock_gles->GetProcTable();
42 gl.DeleteFramebuffers(1, nullptr);
43
44 // Test should still complete.
45 // If we end up mocking DeleteFramebuffers, delete this test.
46}

◆ TEST() [229/399]

impeller::testing::TEST ( MockGLES  ,
CanInitialize   
)

Definition at line 16 of file mock_gles_unittests.cc.

16 {
17 auto mock_gles = MockGLES::Init();
18
19 std::string_view vendor(reinterpret_cast<const char*>(
20 mock_gles->GetProcTable().GetString(GL_VENDOR)));
21 EXPECT_EQ(vendor, "MockGLES");
22}

◆ TEST() [230/399]

impeller::testing::TEST ( MockGLES  ,
CapturesPushAndPopDebugGroup   
)

Definition at line 25 of file mock_gles_unittests.cc.

25 {
26 auto mock_gles = MockGLES::Init();
27
28 auto& gl = mock_gles->GetProcTable();
29 gl.PushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, 0, -1, "test");
30 gl.PopDebugGroupKHR();
31
32 auto calls = mock_gles->GetCapturedCalls();
33 EXPECT_EQ(calls, std::vector<std::string>(
34 {"PushDebugGroupKHR", "PopDebugGroupKHR"}));
35}

◆ TEST() [231/399]

impeller::testing::TEST ( MockVulkanContextTest  ,
DefaultFenceAlwaysReportsSuccess   
)

Definition at line 36 of file mock_vulkan_unittests.cc.

36 {
37 auto const context = MockVulkanContextBuilder().Build();
38 auto const device = context->GetDevice();
39
40 auto fence = device.createFenceUnique({}).value;
41 EXPECT_EQ(vk::Result::eSuccess, device.getFenceStatus(*fence));
42}

◆ TEST() [232/399]

impeller::testing::TEST ( MockVulkanContextTest  ,
IsThreadSafe   
)

Definition at line 13 of file mock_vulkan_unittests.cc.

13 {
14 // In a typical app, there is a single ContextVK per app, shared b/w threads.
15 //
16 // This test ensures that the (mock) ContextVK is thread-safe.
17 auto const context = MockVulkanContextBuilder().Build();
18
19 // Spawn two threads, and have them create a CommandPoolVK each.
20 std::thread thread1([&context]() {
21 auto const pool = context->GetCommandPoolRecycler()->Get();
23 });
24
25 std::thread thread2([&context]() {
26 auto const pool = context->GetCommandPoolRecycler()->Get();
28 });
29
30 thread1.join();
31 thread2.join();
32
33 context->Shutdown();
34}

◆ TEST() [233/399]

impeller::testing::TEST ( MockVulkanContextTest  ,
MockedFenceReportsStatus   
)

Definition at line 44 of file mock_vulkan_unittests.cc.

44 {
45 auto const context = MockVulkanContextBuilder().Build();
46
47 auto const device = context->GetDevice();
48 auto fence = device.createFenceUnique({}).value;
49 MockFence::SetStatus(fence, vk::Result::eNotReady);
50
51 EXPECT_EQ(vk::Result::eNotReady, device.getFenceStatus(fence.get()));
52
53 MockFence::SetStatus(fence, vk::Result::eSuccess);
54 EXPECT_EQ(vk::Result::eSuccess, device.getFenceStatus(*fence));
55}

◆ TEST() [234/399]

impeller::testing::TEST ( PathTest  ,
BoundingBoxCubic   
)

Definition at line 339 of file path_unittests.cc.

339 {
340 PathBuilder builder;
341 auto path =
342 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
343 .TakePath();
344 auto box = path.GetBoundingBox();
345 Rect expected = Rect::MakeXYWH(93.9101, 40, 126.09, 158.862);
346 ASSERT_TRUE(box.has_value());
347 ASSERT_RECT_NEAR(box.value_or(Rect::MakeMaximum()), expected);
348}
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
TRect< Scalar > Rect
Definition rect.h:746

◆ TEST() [235/399]

impeller::testing::TEST ( PathTest  ,
BoundingBoxOfCompositePathIsCorrect   
)

Definition at line 350 of file path_unittests.cc.

350 {
351 PathBuilder builder;
352 builder.AddRoundedRect(Rect::MakeXYWH(10, 10, 300, 300), {50, 50, 50, 50});
353 auto path = builder.TakePath();
354 auto actual = path.GetBoundingBox();
355 Rect expected = Rect::MakeXYWH(10, 10, 300, 300);
356
357 ASSERT_TRUE(actual.has_value());
358 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
359}

◆ TEST() [236/399]

impeller::testing::TEST ( PathTest  ,
CanBeCloned   
)

Definition at line 501 of file path_unittests.cc.

501 {
502 PathBuilder builder;
503 builder.MoveTo({10, 10});
504 builder.LineTo({20, 20});
505 builder.SetBounds(Rect::MakeLTRB(0, 0, 100, 100));
506 builder.SetConvexity(Convexity::kConvex);
507
508 auto path_a = builder.TakePath(FillType::kOdd);
509 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
510 auto path_b = path_a;
511
512 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
513 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
514 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
515
516 auto poly_a = path_a.CreatePolyline(1.0);
517 auto poly_b = path_b.CreatePolyline(1.0);
518
519 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
520 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
521
522 for (auto i = 0u; i < poly_a.points->size(); i++) {
523 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
524 }
525
526 for (auto i = 0u; i < poly_a.contours.size(); i++) {
527 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
528 EXPECT_EQ(poly_a.contours[i].start_direction,
529 poly_b.contours[i].start_direction);
530 }
531}

◆ TEST() [237/399]

impeller::testing::TEST ( PathTest  ,
CloseAfterMoveDoesNotAddNewLines   
)

Definition at line 471 of file path_unittests.cc.

471 {
472 PathBuilder builder;
473 auto path = builder.LineTo({0, 10})
474 .LineTo({10, 10})
475 .MoveTo({30, 30}) // Moves to (30, 30)
476 .Close() // No Op
477 .Close() // Still No op
478 .TakePath();
479
480 EXPECT_EQ(path.GetComponentCount(), 4u);
481 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 2u);
482 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
483}

◆ TEST() [238/399]

impeller::testing::TEST ( PathTest  ,
CloseAtOriginDoesNotAddNewLineSegment   
)

Definition at line 485 of file path_unittests.cc.

485 {
486 PathBuilder builder;
487 // Create a path that has a current position at the origin when close is
488 // called. This should not insert a new line segment
489 auto path = builder.LineTo({10, 0})
490 .LineTo({10, 10})
491 .LineTo({0, 10})
492 .LineTo({0, 0})
493 .Close()
494 .TakePath();
495
496 EXPECT_EQ(path.GetComponentCount(), 6u);
497 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 4u);
498 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
499}

◆ TEST() [239/399]

impeller::testing::TEST ( PathTest  ,
CubicPath   
)

Definition at line 324 of file path_unittests.cc.

324 {
325 PathBuilder builder;
326 auto path =
327 builder.CubicCurveTo(Point(10, 10), Point(-10, -10), Point(20, 20))
328 .TakePath();
329
330 CubicPathComponent cubic;
331 path.GetCubicComponentAtIndex(1, cubic);
332
333 EXPECT_EQ(cubic.p1, Point(0, 0));
334 EXPECT_EQ(cubic.cp1, Point(10, 10));
335 EXPECT_EQ(cubic.cp2, Point(-10, -10));
336 EXPECT_EQ(cubic.p2, Point(20, 20));
337}

◆ TEST() [240/399]

impeller::testing::TEST ( PathTest  ,
CubicPathComponentPolylineDoesNotIncludePointOne   
)

Definition at line 15 of file path_unittests.cc.

15 {
16 CubicPathComponent component({10, 10}, {20, 35}, {35, 20}, {40, 40});
17 std::vector<Point> polyline;
18 component.AppendPolylinePoints(1.0f, polyline);
19 ASSERT_NE(polyline.front().x, 10);
20 ASSERT_NE(polyline.front().y, 10);
21 ASSERT_EQ(polyline.back().x, 40);
22 ASSERT_EQ(polyline.back().y, 40);
23}
const Path::Polyline & polyline
void AppendPolylinePoints(Scalar scale, std::vector< Point > &points) const

◆ TEST() [241/399]

impeller::testing::TEST ( PathTest  ,
EmptyPath   
)

Definition at line 384 of file path_unittests.cc.

384 {
385 auto path = PathBuilder{}.TakePath();
386 ASSERT_EQ(path.GetComponentCount(), 1u);
387
389 path.GetContourComponentAtIndex(0, c);
391
392 Path::Polyline polyline = path.CreatePolyline(1.0f);
393 ASSERT_TRUE(polyline.points->empty());
394 ASSERT_TRUE(polyline.contours.empty());
395}

◆ TEST() [242/399]

impeller::testing::TEST ( PathTest  ,
ExtremaOfCubicPathComponentIsCorrect   
)

Definition at line 361 of file path_unittests.cc.

361 {
362 CubicPathComponent cubic{{11.769268, 252.883148},
363 {-6.2857933, 204.356461},
364 {-4.53997231, 156.552902},
365 {17.0067291, 109.472488}};
366 auto points = cubic.Extrema();
367
368 ASSERT_EQ(points.size(), static_cast<size_t>(3));
369 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
370}
static const int points[]
AI float cubic(float precision, const SkPoint pts[], const VectorXform &vectorXform=VectorXform())

◆ TEST() [243/399]

impeller::testing::TEST ( PathTest  ,
PathAddRectPolylineHasCorrectContourData   
)

Definition at line 160 of file path_unittests.cc.

160 {
162 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
163 .TakePath()
164 .CreatePolyline(1.0f);
165 ASSERT_EQ(polyline.contours.size(), 1u);
166 ASSERT_TRUE(polyline.contours[0].is_closed);
167 ASSERT_EQ(polyline.contours[0].start_index, 0u);
168 ASSERT_EQ(polyline.points->size(), 5u);
169 ASSERT_EQ(polyline.GetPoint(0), Point(50, 60));
170 ASSERT_EQ(polyline.GetPoint(1), Point(70, 60));
171 ASSERT_EQ(polyline.GetPoint(2), Point(70, 80));
172 ASSERT_EQ(polyline.GetPoint(3), Point(50, 80));
173 ASSERT_EQ(polyline.GetPoint(4), Point(50, 60));
174}
Polyline CreatePolyline(Scalar scale, Polyline::PointBufferPtr point_buffer=std::make_unique< std::vector< Point > >(), Polyline::ReclaimPointBufferCallback reclaim=nullptr) const
Definition path.cc:198

◆ TEST() [244/399]

impeller::testing::TEST ( PathTest  ,
PathBuilderDoesNotMutateCopiedPaths   
)

Definition at line 533 of file path_unittests.cc.

533 {
534 auto test_isolation =
535 [](const std::function<void(PathBuilder & builder)>& mutator,
536 bool will_close, Point mutation_offset, const std::string& label) {
537 PathBuilder builder;
538 builder.MoveTo({10, 10});
539 builder.LineTo({20, 20});
540 builder.LineTo({20, 10});
541
542 auto verify_path = [](const Path& path, bool is_mutated, bool is_closed,
543 Point offset, const std::string& label) {
544 if (is_mutated) {
545 // We can only test the initial state before the mutator did
546 // its work. We have >= 3 components and the first 3 components
547 // will match what we saw before the mutation.
548 EXPECT_GE(path.GetComponentCount(), 3u) << label;
549 } else {
550 EXPECT_EQ(path.GetComponentCount(), 3u) << label;
551 }
552 {
553 ContourComponent contour;
554 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour)) << label;
555 EXPECT_EQ(contour.destination, offset + Point(10, 10)) << label;
556 EXPECT_EQ(contour.is_closed, is_closed) << label;
557 }
558 {
559 LinearPathComponent line;
560 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, line)) << label;
561 EXPECT_EQ(line.p1, offset + Point(10, 10)) << label;
562 EXPECT_EQ(line.p2, offset + Point(20, 20)) << label;
563 }
564 {
565 LinearPathComponent line;
566 EXPECT_TRUE(path.GetLinearComponentAtIndex(2, line)) << label;
567 EXPECT_EQ(line.p1, offset + Point(20, 20)) << label;
568 EXPECT_EQ(line.p2, offset + Point(20, 10)) << label;
569 }
570 };
571
572 auto path1 = builder.CopyPath();
573 verify_path(path1, false, false, {},
574 "Initial Path1 state before " + label);
575
576 for (int i = 0; i < 10; i++) {
577 auto path = builder.CopyPath();
578 verify_path(
579 path, false, false, {},
580 "Extra CopyPath #" + std::to_string(i + 1) + " for " + label);
581 }
582 mutator(builder);
583 verify_path(path1, false, false, {},
584 "Path1 state after subsequent " + label);
585
586 auto path2 = builder.CopyPath();
587 verify_path(path1, false, false, {},
588 "Path1 state after subsequent " + label + " and CopyPath");
589 verify_path(path2, true, will_close, mutation_offset,
590 "Initial Path2 state with subsequent " + label);
591 };
592
593 test_isolation(
594 [](PathBuilder& builder) { //
595 builder.SetConvexity(Convexity::kConvex);
596 },
597 false, {}, "SetConvex");
598
599 test_isolation(
600 [](PathBuilder& builder) { //
601 builder.SetConvexity(Convexity::kUnknown);
602 },
603 false, {}, "SetUnknownConvex");
604
605 test_isolation(
606 [](PathBuilder& builder) { //
607 builder.Close();
608 },
609 true, {}, "Close");
610
611 test_isolation(
612 [](PathBuilder& builder) {
613 builder.MoveTo({20, 30}, false);
614 },
615 false, {}, "Absolute MoveTo");
616
617 test_isolation(
618 [](PathBuilder& builder) {
619 builder.MoveTo({20, 30}, true);
620 },
621 false, {}, "Relative MoveTo");
622
623 test_isolation(
624 [](PathBuilder& builder) {
625 builder.LineTo({20, 30}, false);
626 },
627 false, {}, "Absolute LineTo");
628
629 test_isolation(
630 [](PathBuilder& builder) {
631 builder.LineTo({20, 30}, true);
632 },
633 false, {}, "Relative LineTo");
634
635 test_isolation(
636 [](PathBuilder& builder) { //
637 builder.HorizontalLineTo(100, false);
638 },
639 false, {}, "Absolute HorizontalLineTo");
640
641 test_isolation(
642 [](PathBuilder& builder) { //
643 builder.HorizontalLineTo(100, true);
644 },
645 false, {}, "Relative HorizontalLineTo");
646
647 test_isolation(
648 [](PathBuilder& builder) { //
649 builder.VerticalLineTo(100, false);
650 },
651 false, {}, "Absolute VerticalLineTo");
652
653 test_isolation(
654 [](PathBuilder& builder) { //
655 builder.VerticalLineTo(100, true);
656 },
657 false, {}, "Relative VerticalLineTo");
658
659 test_isolation(
660 [](PathBuilder& builder) {
661 builder.QuadraticCurveTo({20, 30}, {30, 20}, false);
662 },
663 false, {}, "Absolute QuadraticCurveTo");
664
665 test_isolation(
666 [](PathBuilder& builder) {
667 builder.QuadraticCurveTo({20, 30}, {30, 20}, true);
668 },
669 false, {}, "Relative QuadraticCurveTo");
670
671 test_isolation(
672 [](PathBuilder& builder) {
673 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, false);
674 },
675 false, {}, "Absolute CubicCurveTo");
676
677 test_isolation(
678 [](PathBuilder& builder) {
679 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, true);
680 },
681 false, {}, "Relative CubicCurveTo");
682
683 test_isolation(
684 [](PathBuilder& builder) {
685 builder.AddLine({100, 100}, {150, 100});
686 },
687 false, {}, "AddLine");
688
689 test_isolation(
690 [](PathBuilder& builder) {
691 builder.AddRect(Rect::MakeLTRB(100, 100, 120, 120));
692 },
693 false, {}, "AddRect");
694
695 test_isolation(
696 [](PathBuilder& builder) {
697 builder.AddOval(Rect::MakeLTRB(100, 100, 120, 120));
698 },
699 false, {}, "AddOval");
700
701 test_isolation(
702 [](PathBuilder& builder) {
703 builder.AddCircle({100, 100}, 20);
704 },
705 false, {}, "AddCircle");
706
707 test_isolation(
708 [](PathBuilder& builder) {
709 builder.AddArc(Rect::MakeLTRB(100, 100, 120, 120), Degrees(10),
710 Degrees(170));
711 },
712 false, {}, "AddArc");
713
714 test_isolation(
715 [](PathBuilder& builder) {
716 builder.AddQuadraticCurve({100, 100}, {150, 100}, {150, 150});
717 },
718 false, {}, "AddQuadraticCurve");
719
720 test_isolation(
721 [](PathBuilder& builder) {
722 builder.AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
723 },
724 false, {}, "AddCubicCurve");
725
726 test_isolation(
727 [](PathBuilder& builder) {
728 builder.Shift({23, 42});
729 },
730 false, {23, 42}, "Shift");
731}
static SkPath path1()
static SkPath path2()
CanvasPath Path
Definition dart_ui.cc:58
Point offset

◆ TEST() [245/399]

impeller::testing::TEST ( PathTest  ,
PathBuilderSetsCorrectContourPropertiesForAddCommands   
)

Definition at line 44 of file path_unittests.cc.

44 {
45 // Closed shapes.
46 {
47 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
48 ContourComponent contour;
49 path.GetContourComponentAtIndex(0, contour);
50 EXPECT_POINT_NEAR(contour.destination, Point(100, 50));
51 EXPECT_TRUE(contour.is_closed);
52 }
53
54 {
55 Path path =
56 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
57 ContourComponent contour;
58 path.GetContourComponentAtIndex(0, contour);
59 EXPECT_POINT_NEAR(contour.destination, Point(150, 100));
60 EXPECT_TRUE(contour.is_closed);
61 }
62
63 {
64 Path path =
65 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
66 ContourComponent contour;
67 path.GetContourComponentAtIndex(0, contour);
68 EXPECT_POINT_NEAR(contour.destination, Point(100, 100));
69 EXPECT_TRUE(contour.is_closed);
70 }
71
72 {
73 Path path = PathBuilder{}
74 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10)
75 .TakePath();
76 ContourComponent contour;
77 path.GetContourComponentAtIndex(0, contour);
78 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
79 EXPECT_TRUE(contour.is_closed);
80 }
81
82 {
83 Path path =
84 PathBuilder{}
85 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20))
86 .TakePath();
87 ContourComponent contour;
88 path.GetContourComponentAtIndex(0, contour);
89 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
90 EXPECT_TRUE(contour.is_closed);
91 }
92
93 // Open shapes.
94 {
95 Point p(100, 100);
96 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
97 ContourComponent contour;
98 path.GetContourComponentAtIndex(0, contour);
99 ASSERT_POINT_NEAR(contour.destination, p);
100 ASSERT_FALSE(contour.is_closed);
101 }
102
103 {
104 Path path =
105 PathBuilder{}
106 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
107 .TakePath();
108 ContourComponent contour;
109 path.GetContourComponentAtIndex(0, contour);
110 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
111 ASSERT_FALSE(contour.is_closed);
112 }
113
114 {
115 Path path = PathBuilder{}
116 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
117 .TakePath();
118 ContourComponent contour;
119 path.GetContourComponentAtIndex(0, contour);
120 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
121 ASSERT_FALSE(contour.is_closed);
122 }
123}
PathBuilder & AddCircle(const Point &center, Scalar radius)
#define EXPECT_POINT_NEAR(a, b)
TSize< Scalar > Size
Definition size.h:137

◆ TEST() [246/399]

impeller::testing::TEST ( PathTest  ,
PathBuilderWillComputeBounds   
)

Definition at line 268 of file path_unittests.cc.

268 {
269 PathBuilder builder;
270 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
271
272 ASSERT_EQ(path_1.GetBoundingBox().value_or(Rect::MakeMaximum()),
273 Rect::MakeLTRB(0, 0, 1, 1));
274
275 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
276
277 // Verify that PathBuilder recomputes the bounds.
278 ASSERT_EQ(path_2.GetBoundingBox().value_or(Rect::MakeMaximum()),
279 Rect::MakeLTRB(-1, -1, 1, 1));
280
281 // PathBuilder can set the bounds to whatever it wants
282 auto path_3 = builder.AddLine({0, 0}, {1, 1})
283 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
284 .TakePath();
285
286 ASSERT_EQ(path_3.GetBoundingBox().value_or(Rect::MakeMaximum()),
287 Rect::MakeLTRB(0, 0, 100, 100));
288}

◆ TEST() [247/399]

impeller::testing::TEST ( PathTest  ,
PathCreatePolyLineDoesNotDuplicatePoints   
)

Definition at line 25 of file path_unittests.cc.

25 {
26 PathBuilder builder;
27 builder.MoveTo({10, 10});
28 builder.LineTo({20, 20});
29 builder.LineTo({30, 30});
30 builder.MoveTo({40, 40});
31 builder.LineTo({50, 50});
32
33 auto polyline = builder.TakePath().CreatePolyline(1.0f);
34
35 ASSERT_EQ(polyline.contours.size(), 2u);
36 ASSERT_EQ(polyline.points->size(), 5u);
37 ASSERT_EQ(polyline.GetPoint(0).x, 10);
38 ASSERT_EQ(polyline.GetPoint(1).x, 20);
39 ASSERT_EQ(polyline.GetPoint(2).x, 30);
40 ASSERT_EQ(polyline.GetPoint(3).x, 40);
41 ASSERT_EQ(polyline.GetPoint(4).x, 50);
42}

◆ TEST() [248/399]

impeller::testing::TEST ( PathTest  ,
PathCreatePolylineGeneratesCorrectContourData   
)

Definition at line 125 of file path_unittests.cc.

125 {
127 .AddLine({100, 100}, {200, 100})
128 .MoveTo({100, 200})
129 .LineTo({150, 250})
130 .LineTo({200, 200})
131 .Close()
132 .TakePath()
133 .CreatePolyline(1.0f);
134 ASSERT_EQ(polyline.points->size(), 6u);
135 ASSERT_EQ(polyline.contours.size(), 2u);
136 ASSERT_EQ(polyline.contours[0].is_closed, false);
137 ASSERT_EQ(polyline.contours[0].start_index, 0u);
138 ASSERT_EQ(polyline.contours[1].is_closed, true);
139 ASSERT_EQ(polyline.contours[1].start_index, 2u);
140}
PathBuilder & AddLine(const Point &p1, const Point &p2)
Move to point p1, then insert a line from p1 to p2.
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)

◆ TEST() [249/399]

impeller::testing::TEST ( PathTest  ,
PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect   
)

Definition at line 372 of file path_unittests.cc.

372 {
373 PathBuilder builder;
374 // Straight diagonal line.
375 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
376 auto path = builder.TakePath();
377 auto actual = path.GetBoundingBox();
378 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
379
380 ASSERT_TRUE(actual.has_value());
381 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
382}

◆ TEST() [250/399]

impeller::testing::TEST ( PathTest  ,
PathHorizontalLine   
)

Definition at line 290 of file path_unittests.cc.

290 {
291 PathBuilder builder;
292 auto path = builder.HorizontalLineTo(10).TakePath();
293
295 path.GetLinearComponentAtIndex(1, linear);
296
297 EXPECT_EQ(linear.p1, Point(0, 0));
298 EXPECT_EQ(linear.p2, Point(10, 0));
299}
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)

◆ TEST() [251/399]

impeller::testing::TEST ( PathTest  ,
PathPolylineDuplicatesAreRemovedForSameContour   
)

Definition at line 176 of file path_unittests.cc.

176 {
179 .MoveTo({50, 50})
180 .LineTo({50, 50}) // Insert duplicate at beginning of contour.
181 .LineTo({100, 50})
182 .LineTo({100, 50}) // Insert duplicate at contour join.
183 .LineTo({100, 100})
184 .Close() // Implicitly insert duplicate {50, 50} across contours.
185 .LineTo({0, 50})
186 .LineTo({0, 100})
187 .LineTo({0, 100}) // Insert duplicate at end of contour.
188 .TakePath()
189 .CreatePolyline(1.0f);
190 ASSERT_EQ(polyline.contours.size(), 2u);
191 ASSERT_EQ(polyline.contours[0].start_index, 0u);
192 ASSERT_TRUE(polyline.contours[0].is_closed);
193 ASSERT_EQ(polyline.contours[1].start_index, 4u);
194 ASSERT_FALSE(polyline.contours[1].is_closed);
195 ASSERT_EQ(polyline.points->size(), 7u);
196 ASSERT_EQ(polyline.GetPoint(0), Point(50, 50));
197 ASSERT_EQ(polyline.GetPoint(1), Point(100, 50));
198 ASSERT_EQ(polyline.GetPoint(2), Point(100, 100));
199 ASSERT_EQ(polyline.GetPoint(3), Point(50, 50));
200 ASSERT_EQ(polyline.GetPoint(4), Point(50, 50));
201 ASSERT_EQ(polyline.GetPoint(5), Point(0, 50));
202 ASSERT_EQ(polyline.GetPoint(6), Point(0, 100));
203}
PathBuilder & MoveTo(Point point, bool relative=false)

◆ TEST() [252/399]

impeller::testing::TEST ( PathTest  ,
PathShifting   
)

Definition at line 232 of file path_unittests.cc.

232 {
233 PathBuilder builder{};
234 auto path =
235 builder.AddLine(Point(0, 0), Point(10, 10))
236 .AddQuadraticCurve(Point(10, 10), Point(15, 15), Point(20, 20))
237 .AddCubicCurve(Point(20, 20), Point(25, 25), Point(-5, -5),
238 Point(30, 30))
239 .Close()
240 .Shift(Point(1, 1))
241 .TakePath();
242
246 CubicPathComponent cubic;
247
248 ASSERT_TRUE(path.GetContourComponentAtIndex(0, contour));
249 ASSERT_TRUE(path.GetLinearComponentAtIndex(1, linear));
250 ASSERT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
251 ASSERT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
252
253 EXPECT_EQ(contour.destination, Point(1, 1));
254
255 EXPECT_EQ(linear.p1, Point(1, 1));
256 EXPECT_EQ(linear.p2, Point(11, 11));
257
258 EXPECT_EQ(quad.cp, Point(16, 16));
259 EXPECT_EQ(quad.p1, Point(11, 11));
260 EXPECT_EQ(quad.p2, Point(21, 21));
261
262 EXPECT_EQ(cubic.cp1, Point(26, 26));
263 EXPECT_EQ(cubic.cp2, Point(-4, -4));
264 EXPECT_EQ(cubic.p1, Point(21, 21));
265 EXPECT_EQ(cubic.p2, Point(31, 31));
266}

◆ TEST() [253/399]

impeller::testing::TEST ( PathTest  ,
PathVerticalLine   
)

Definition at line 301 of file path_unittests.cc.

301 {
302 PathBuilder builder;
303 auto path = builder.VerticalLineTo(10).TakePath();
304
306 path.GetLinearComponentAtIndex(1, linear);
307
308 EXPECT_EQ(linear.p1, Point(0, 0));
309 EXPECT_EQ(linear.p2, Point(0, 10));
310}

◆ TEST() [254/399]

impeller::testing::TEST ( PathTest  ,
PolylineBufferReuse   
)

Definition at line 205 of file path_unittests.cc.

205 {
206 auto point_buffer = std::make_unique<std::vector<Point>>();
207 auto point_buffer_address = reinterpret_cast<uintptr_t>(point_buffer.get());
210 .MoveTo({50, 50})
211 .LineTo({100, 100})
212 .TakePath()
213 .CreatePolyline(
214 1.0f, std::move(point_buffer),
215 [point_buffer_address](
216 Path::Polyline::PointBufferPtr point_buffer) {
217 ASSERT_EQ(point_buffer->size(), 0u);
218 ASSERT_EQ(point_buffer_address,
219 reinterpret_cast<uintptr_t>(point_buffer.get()));
220 });
221}

◆ TEST() [255/399]

impeller::testing::TEST ( PathTest  ,
PolylineFailsWithNullptrBuffer   
)

Definition at line 223 of file path_unittests.cc.

223 {
224 EXPECT_DEATH_IF_SUPPORTED(PathBuilder{}
225 .MoveTo({50, 50})
226 .LineTo({100, 100})
227 .TakePath()
228 .CreatePolyline(1.0f, nullptr),
229 "");
230}

◆ TEST() [256/399]

impeller::testing::TEST ( PathTest  ,
PolylineGetContourPointBoundsReturnsCorrectRanges   
)

Definition at line 142 of file path_unittests.cc.

142 {
144 .AddLine({100, 100}, {200, 100})
145 .MoveTo({100, 200})
146 .LineTo({150, 250})
147 .LineTo({200, 200})
148 .Close()
149 .TakePath()
150 .CreatePolyline(1.0f);
151 size_t a1, a2, b1, b2;
152 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
153 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
154 ASSERT_EQ(a1, 0u);
155 ASSERT_EQ(a2, 2u);
156 ASSERT_EQ(b1, 2u);
157 ASSERT_EQ(b2, 6u);
158}

◆ TEST() [257/399]

impeller::testing::TEST ( PathTest  ,
QuadradicPath   
)

Definition at line 312 of file path_unittests.cc.

312 {
313 PathBuilder builder;
314 auto path = builder.QuadraticCurveTo(Point(10, 10), Point(20, 20)).TakePath();
315
317 path.GetQuadraticComponentAtIndex(1, quad);
318
319 EXPECT_EQ(quad.p1, Point(0, 0));
320 EXPECT_EQ(quad.cp, Point(10, 10));
321 EXPECT_EQ(quad.p2, Point(20, 20));
322}

◆ TEST() [258/399]

impeller::testing::TEST ( PathTest  ,
RepeatCloseDoesNotAddNewLines   
)

Definition at line 457 of file path_unittests.cc.

457 {
458 PathBuilder builder;
459 auto path = builder.LineTo({0, 10})
460 .LineTo({10, 10})
461 .Close() // Returns to (0, 0)
462 .Close() // No Op
463 .Close() // Still No op
464 .TakePath();
465
466 EXPECT_EQ(path.GetComponentCount(), 5u);
467 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 3u);
468 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
469}

◆ TEST() [259/399]

impeller::testing::TEST ( PathTest  ,
SimplePath   
)

Definition at line 397 of file path_unittests.cc.

397 {
398 PathBuilder builder;
399
400 auto path = builder.AddLine({0, 0}, {100, 100})
401 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
402 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
403 .TakePath();
404
405 ASSERT_EQ(path.GetComponentCount(), 6u);
406 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
407 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
408 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
409 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 3u);
410
411 path.EnumerateComponents(
412 [](size_t index, const LinearPathComponent& linear) {
413 Point p1(0, 0);
414 Point p2(100, 100);
415 ASSERT_EQ(index, 1u);
416 ASSERT_EQ(linear.p1, p1);
417 ASSERT_EQ(linear.p2, p2);
418 },
419 [](size_t index, const QuadraticPathComponent& quad) {
420 Point p1(100, 100);
421 Point cp(200, 200);
422 Point p2(300, 300);
423 ASSERT_EQ(index, 3u);
424 ASSERT_EQ(quad.p1, p1);
425 ASSERT_EQ(quad.cp, cp);
426 ASSERT_EQ(quad.p2, p2);
427 },
428 [](size_t index, const CubicPathComponent& cubic) {
429 Point p1(300, 300);
430 Point cp1(400, 400);
431 Point cp2(500, 500);
432 Point p2(600, 600);
433 ASSERT_EQ(index, 5u);
434 ASSERT_EQ(cubic.p1, p1);
435 ASSERT_EQ(cubic.cp1, cp1);
436 ASSERT_EQ(cubic.cp2, cp2);
437 ASSERT_EQ(cubic.p2, p2);
438 },
439 [](size_t index, const ContourComponent& contour) {
440 // There is an initial countour added for each curve.
441 if (index == 0u) {
442 Point p1(0, 0);
443 ASSERT_EQ(contour.destination, p1);
444 } else if (index == 2u) {
445 Point p1(100, 100);
446 ASSERT_EQ(contour.destination, p1);
447 } else if (index == 4u) {
448 Point p1(300, 300);
449 ASSERT_EQ(contour.destination, p1);
450 } else {
451 ASSERT_FALSE(true);
452 }
453 ASSERT_FALSE(contour.is_closed);
454 });
455}

◆ TEST() [260/399]

impeller::testing::TEST ( PipelineDescriptorTest  ,
PrimitiveTypeHashEquality   
)

Definition at line 13 of file pipeline_descriptor_unittests.cc.

13 {
16
17 ASSERT_TRUE(descA.IsEqual(descB));
18 ASSERT_EQ(descA.GetHash(), descB.GetHash());
19
20 descA.SetPrimitiveType(PrimitiveType::kTriangleStrip);
21
22 ASSERT_FALSE(descA.IsEqual(descB));
23 ASSERT_NE(descA.GetHash(), descB.GetHash());
24}
std::size_t GetHash() const override
bool IsEqual(const PipelineDescriptor &other) const override
void SetPrimitiveType(PrimitiveType type)

◆ TEST() [261/399]

impeller::testing::TEST ( PoolTest  ,
Overload   
)

Definition at line 47 of file pool_unittests.cc.

47 {
48 Pool<Foobar> pool(1'000);
49 {
50 std::vector<std::shared_ptr<Foobar>> values;
51 values.reserve(20);
52 for (int i = 0; i < 20; i++) {
53 values.push_back(pool.Grab());
54 }
55 for (const auto& value : values) {
56 value->SetSize(100);
57 pool.Recycle(value);
58 }
59 }
60 EXPECT_EQ(pool.GetSize(), 1'000u);
61}
A thread-safe pool with a limited byte size.
Definition pool.h:17

◆ TEST() [262/399]

impeller::testing::TEST ( PoolTest  ,
Simple   
)

Definition at line 33 of file pool_unittests.cc.

33 {
34 Pool<Foobar> pool(1'000);
35 {
36 auto grabbed = pool.Grab();
37 grabbed->SetSize(123);
38 pool.Recycle(grabbed);
39 EXPECT_EQ(pool.GetSize(), 123u);
40 }
41 auto grabbed = pool.Grab();
42 EXPECT_EQ(grabbed->GetSize(), 123u);
43 EXPECT_TRUE(grabbed->GetIsReset());
44 EXPECT_EQ(pool.GetSize(), 0u);
45}

◆ TEST() [263/399]

impeller::testing::TEST ( ProcTableGLES  ,
ResolvesCorrectClearDepthProcOnDesktopGL   
)

Definition at line 28 of file proc_table_gles_unittests.cc.

28 {
29 auto mock_gles = MockGLES::Init(std::nullopt, "OpenGL 4.0");
30 EXPECT_FALSE(mock_gles->GetProcTable().GetDescription()->IsES());
31
34}
#define FOR_EACH_IMPELLER_DESKTOP_ONLY_PROC(PROC)
#define FOR_EACH_IMPELLER_ES_ONLY_PROC(PROC)
#define EXPECT_AVAILABLE(proc_ivar)
#define EXPECT_UNAVAILABLE(proc_ivar)

◆ TEST() [264/399]

impeller::testing::TEST ( ProcTableGLES  ,
ResolvesCorrectClearDepthProcOnES   
)

Definition at line 20 of file proc_table_gles_unittests.cc.

20 {
21 auto mock_gles = MockGLES::Init(std::nullopt, "OpenGL ES 3.0");
22 EXPECT_TRUE(mock_gles->GetProcTable().GetDescription()->IsES());
23
26}

◆ TEST() [265/399]

impeller::testing::TEST ( RectTest  ,
ContainsFloatingPoint   
)

Definition at line 1271 of file rect_unittests.cc.

1271 {
1272 auto rect1 =
1273 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1274 auto rect2 = Rect::MakeXYWH(724.f, 618.f, 600.f, 300.f);
1275 EXPECT_TRUE(rect1.Contains(rect2));
1276}

◆ TEST() [266/399]

impeller::testing::TEST ( RectTest  ,
EmptyIRectDoesNotIntersect   
)

Definition at line 854 of file rect_unittests.cc.

854 {
855 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
856
857 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
858 const std::string& label) {
859 EXPECT_FALSE(IRect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
860 << label << " with Top/Bottom swapped";
861 EXPECT_FALSE(IRect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
862 << label << " with Left/Right swapped";
863 EXPECT_FALSE(IRect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
864 << label << " with all sides swapped";
865 };
866
867 test(20, 20, 30, 30, "Above and Left");
868 test(70, 20, 80, 30, "Above");
869 test(120, 20, 130, 30, "Above and Right");
870 test(120, 70, 130, 80, "Right");
871 test(120, 120, 130, 130, "Below and Right");
872 test(70, 120, 80, 130, "Below");
873 test(20, 120, 30, 130, "Below and Left");
874 test(20, 70, 30, 80, "Left");
875
876 test(70, 70, 80, 80, "Inside");
877
878 test(40, 70, 60, 80, "Straddling Left");
879 test(70, 40, 80, 60, "Straddling Top");
880 test(90, 70, 110, 80, "Straddling Right");
881 test(70, 90, 80, 110, "Straddling Bottom");
882}

◆ TEST() [267/399]

impeller::testing::TEST ( RectTest  ,
EmptyRectDoesNotIntersect   
)

Definition at line 824 of file rect_unittests.cc.

824 {
825 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
826
827 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
828 const std::string& label) {
829 EXPECT_FALSE(Rect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
830 << label << " with Top/Bottom swapped";
831 EXPECT_FALSE(Rect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
832 << label << " with Left/Right swapped";
833 EXPECT_FALSE(Rect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
834 << label << " with all sides swapped";
835 };
836
837 test(20, 20, 30, 30, "Above and Left");
838 test(70, 20, 80, 30, "Above");
839 test(120, 20, 130, 30, "Above and Right");
840 test(120, 70, 130, 80, "Right");
841 test(120, 120, 130, 130, "Below and Right");
842 test(70, 120, 80, 130, "Below");
843 test(20, 120, 30, 130, "Below and Left");
844 test(20, 70, 30, 80, "Left");
845
846 test(70, 70, 80, 80, "Inside");
847
848 test(40, 70, 60, 80, "Straddling Left");
849 test(70, 40, 80, 60, "Straddling Top");
850 test(90, 70, 110, 80, "Straddling Right");
851 test(70, 90, 80, 110, "Straddling Bottom");
852}

◆ TEST() [268/399]

impeller::testing::TEST ( RectTest  ,
GetCenter   
)

Definition at line 1194 of file rect_unittests.cc.

1194 {
1195 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1196 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1197 EXPECT_EQ(Rect::MakeMaximum().GetCenter(), Point(0, 0));
1198
1199 // Note that we expect a Point as the answer from an IRect
1200 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1201 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1202 EXPECT_EQ(IRect::MakeMaximum().GetCenter(), Point(0, 0));
1203}

◆ TEST() [269/399]

impeller::testing::TEST ( RectTest  ,
IRectArea   
)

Definition at line 980 of file rect_unittests.cc.

980 {
981 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
982 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
983 EXPECT_EQ(IRect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
984 EXPECT_EQ(IRect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
985 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
986 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
987}

◆ TEST() [270/399]

impeller::testing::TEST ( RectTest  ,
IRectContainsIPoint   
)

Definition at line 2193 of file rect_unittests.cc.

2193 {
2194 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2195 const std::string& label) {
2196 ASSERT_FALSE(rect.IsEmpty());
2197
2198 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2199 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2200 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2201 };
2202
2203 auto test_inside = [&check_empty_flips](const IRect& rect,
2204 const IPoint& point) {
2205 ASSERT_FALSE(rect.IsEmpty()) << rect;
2206
2207 std::stringstream stream;
2208 stream << rect << " contains " << point;
2209 auto label = stream.str();
2210
2211 EXPECT_TRUE(rect.Contains(point)) << label;
2212 check_empty_flips(rect, point, label);
2213 };
2214
2215 auto test_outside = [&check_empty_flips](const IRect& rect,
2216 const IPoint& point) {
2217 ASSERT_FALSE(rect.IsEmpty()) << rect;
2218
2219 std::stringstream stream;
2220 stream << rect << " contains " << point;
2221 auto label = stream.str();
2222
2223 EXPECT_FALSE(rect.Contains(point)) << label;
2224 check_empty_flips(rect, point, label);
2225 };
2226
2227 {
2228 // Origin is inclusive
2229 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2230 auto p = IPoint(100, 100);
2231
2232 test_inside(r, p);
2233 }
2234 {
2235 // Size is exclusive
2236 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2237 auto p = IPoint(200, 200);
2238
2239 test_outside(r, p);
2240 }
2241 {
2242 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2243 auto p = IPoint(99, 99);
2244
2245 test_outside(r, p);
2246 }
2247 {
2248 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2249 auto p = IPoint(199, 199);
2250
2251 test_inside(r, p);
2252 }
2253
2254 {
2255 auto r = IRect::MakeMaximum();
2256 auto p = IPoint(199, 199);
2257
2258 test_inside(r, p);
2259 }
2260}
static constexpr R flip_lrtb(R rect)

◆ TEST() [271/399]

impeller::testing::TEST ( RectTest  ,
IRectContainsIRect   
)

Definition at line 2377 of file rect_unittests.cc.

2377 {
2378 auto check_empty_flips = [](const IRect& a, const IRect& b,
2379 const std::string& label) {
2380 ASSERT_FALSE(a.IsEmpty());
2381 // test b rects are allowed to have 0 w/h, but not be backwards
2382 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2383
2384 // unflipped a vs flipped (empty) b yields true
2385 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2386 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2387 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2388
2389 // flipped (empty) a vs unflipped b yields false
2390 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2391 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2392 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2393
2394 // flipped (empty) a vs flipped (empty) b yields empty
2395 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2396 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2397 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2398 };
2399
2400 auto test_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2401 ASSERT_FALSE(a.IsEmpty()) << a;
2402 // test b rects are allowed to have 0 w/h, but not be backwards
2403 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2404
2405 std::stringstream stream;
2406 stream << a << " contains " << b;
2407 auto label = stream.str();
2408
2409 EXPECT_TRUE(a.Contains(b)) << label;
2410 check_empty_flips(a, b, label);
2411 };
2412
2413 auto test_not_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2414 ASSERT_FALSE(a.IsEmpty()) << a;
2415 // If b was empty, it would be contained and should not be tested with
2416 // this function - use |test_inside| instead.
2417 ASSERT_FALSE(b.IsEmpty()) << b;
2418
2419 std::stringstream stream;
2420 stream << a << " contains " << b;
2421 auto label = stream.str();
2422
2423 EXPECT_FALSE(a.Contains(b)) << label;
2424 check_empty_flips(a, b, label);
2425 };
2426
2427 {
2428 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2429
2430 test_inside(a, a);
2431 }
2432 {
2433 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2434 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2435
2436 test_inside(a, b);
2437 }
2438 {
2439 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2440 auto b = IRect::MakeXYWH(150, 150, 20, 20);
2441
2442 test_inside(a, b);
2443 }
2444 {
2445 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2446 auto b = IRect::MakeXYWH(150, 150, 100, 100);
2447
2448 test_not_inside(a, b);
2449 }
2450 {
2451 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2452 auto b = IRect::MakeXYWH(50, 50, 100, 100);
2453
2454 test_not_inside(a, b);
2455 }
2456 {
2457 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2458 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2459
2460 test_not_inside(a, b);
2461 }
2462 {
2463 auto a = IRect::MakeMaximum();
2464 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2465
2466 test_inside(a, b);
2467 }
2468}

◆ TEST() [272/399]

impeller::testing::TEST ( RectTest  ,
IRectCopy   
)

Definition at line 641 of file rect_unittests.cc.

641 {
642 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
643 IRect copy = rect;
644
645 EXPECT_EQ(rect, copy);
646 EXPECT_EQ(copy.GetLeft(), 5);
647 EXPECT_EQ(copy.GetTop(), 10);
648 EXPECT_EQ(copy.GetRight(), 20);
649 EXPECT_EQ(copy.GetBottom(), 25);
650 EXPECT_EQ(copy.GetX(), 5);
651 EXPECT_EQ(copy.GetY(), 10);
652 EXPECT_EQ(copy.GetWidth(), 15);
653 EXPECT_EQ(copy.GetHeight(), 15);
654 EXPECT_FALSE(copy.IsEmpty());
655}
Definition copy.py:1

◆ TEST() [273/399]

impeller::testing::TEST ( RectTest  ,
IRectCutOut   
)

Definition at line 2622 of file rect_unittests.cc.

2622 {
2623 IRect cull_rect = IRect::MakeLTRB(20, 20, 40, 40);
2624
2625 auto check_empty_flips = [&cull_rect](const IRect& diff_rect,
2626 const std::string& label) {
2627 EXPECT_FALSE(diff_rect.IsEmpty());
2628 EXPECT_FALSE(cull_rect.IsEmpty());
2629
2630 // unflipped cull_rect vs flipped(empty) diff_rect
2631 // == cull_rect
2632 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2633 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2634 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2635 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2636 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2637 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2638
2639 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2640 // == empty
2641 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2642 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2643 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2644 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2645 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2646 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2647
2648 // flipped(empty) cull_rect vs unflipped diff_rect
2649 // == empty
2650 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2651 << label;
2652 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), IRect())
2653 << label;
2654 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2655 << label;
2656 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), IRect())
2657 << label;
2658 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2659 << label;
2660 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), IRect())
2661 << label;
2662 };
2663
2664 auto non_reducing = [&cull_rect, &check_empty_flips](
2665 const IRect& diff_rect, const std::string& label) {
2666 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2667 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2668 check_empty_flips(diff_rect, label);
2669 };
2670
2671 auto reducing = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2672 const IRect& result_rect,
2673 const std::string& label) {
2674 EXPECT_TRUE(!result_rect.IsEmpty());
2675 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2676 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2677 check_empty_flips(diff_rect, label);
2678 };
2679
2680 auto emptying = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2681 const std::string& label) {
2682 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2683 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), IRect()) << label;
2684 check_empty_flips(diff_rect, label);
2685 };
2686
2687 // Skim the corners and edge
2688 non_reducing(IRect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2689 non_reducing(IRect::MakeLTRB(20, 10, 40, 20), "Above");
2690 non_reducing(IRect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2691 non_reducing(IRect::MakeLTRB(40, 20, 50, 40), "Right");
2692 non_reducing(IRect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2693 non_reducing(IRect::MakeLTRB(20, 40, 40, 50), "Below");
2694 non_reducing(IRect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2695 non_reducing(IRect::MakeLTRB(10, 20, 20, 40), "Left");
2696
2697 // Overlap corners
2698 non_reducing(IRect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2699 non_reducing(IRect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2700 non_reducing(IRect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2701 non_reducing(IRect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2702
2703 // Overlap edges, but not across an entire side
2704 non_reducing(IRect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2705 non_reducing(IRect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2706 non_reducing(IRect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2707 non_reducing(IRect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2708 non_reducing(IRect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2709 non_reducing(IRect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2710 non_reducing(IRect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2711 non_reducing(IRect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2712
2713 // Slice all the way through the middle
2714 non_reducing(IRect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2715 non_reducing(IRect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2716
2717 // Slice off each edge
2718 reducing(IRect::MakeLTRB(20, 15, 40, 25), //
2719 IRect::MakeLTRB(20, 25, 40, 40), //
2720 "Slice off top");
2721 reducing(IRect::MakeLTRB(35, 20, 45, 40), //
2722 IRect::MakeLTRB(20, 20, 35, 40), //
2723 "Slice off right");
2724 reducing(IRect::MakeLTRB(20, 35, 40, 45), //
2725 IRect::MakeLTRB(20, 20, 40, 35), //
2726 "Slice off bottom");
2727 reducing(IRect::MakeLTRB(15, 20, 25, 40), //
2728 IRect::MakeLTRB(25, 20, 40, 40), //
2729 "Slice off left");
2730
2731 // cull rect contains diff rect
2732 non_reducing(IRect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2733
2734 // cull rect equals diff rect
2735 emptying(cull_rect, "Perfectly covering");
2736
2737 // diff rect contains cull rect
2738 emptying(IRect::MakeLTRB(15, 15, 45, 45), "Smothering");
2739}
TRect< int64_t > IRect
Definition rect.h:747
constexpr std::optional< TRect< T > > Cutout(const TRect &o) const
Returns the new boundary rectangle that would result from this rectangle being cut out by the specifi...
Definition rect.h:521
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition rect.h:264
constexpr TRect CutoutOrEmpty(const TRect &o) const
Definition rect.h:561

◆ TEST() [274/399]

impeller::testing::TEST ( RectTest  ,
IRectDefaultConstructor   
)

Definition at line 59 of file rect_unittests.cc.

59 {
60 IRect rect = IRect();
61
62 EXPECT_EQ(rect.GetLeft(), 0);
63 EXPECT_EQ(rect.GetTop(), 0);
64 EXPECT_EQ(rect.GetRight(), 0);
65 EXPECT_EQ(rect.GetBottom(), 0);
66 EXPECT_EQ(rect.GetX(), 0);
67 EXPECT_EQ(rect.GetY(), 0);
68 EXPECT_EQ(rect.GetWidth(), 0);
69 EXPECT_EQ(rect.GetHeight(), 0);
70 EXPECT_TRUE(rect.IsEmpty());
71}

◆ TEST() [275/399]

impeller::testing::TEST ( RectTest  ,
IRectDoesNotIntersectEmpty   
)

Definition at line 794 of file rect_unittests.cc.

794 {
795 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
796
797 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
798 const std::string& label) {
799 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(l, b, r, t)))
800 << label << " with Top/Bottom swapped";
801 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, b, l, t)))
802 << label << " with Left/Right swapped";
803 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, t, l, b)))
804 << label << " with all sides swapped";
805 };
806
807 test(20, 20, 30, 30, "Above and Left");
808 test(70, 20, 80, 30, "Above");
809 test(120, 20, 130, 30, "Above and Right");
810 test(120, 70, 130, 80, "Right");
811 test(120, 120, 130, 130, "Below and Right");
812 test(70, 120, 80, 130, "Below");
813 test(20, 120, 30, 130, "Below and Left");
814 test(20, 70, 30, 80, "Left");
815
816 test(70, 70, 80, 80, "Inside");
817
818 test(40, 70, 60, 80, "Straddling Left");
819 test(70, 40, 80, 60, "Straddling Top");
820 test(90, 70, 110, 80, "Straddling Right");
821 test(70, 90, 80, 110, "Straddling Bottom");
822}

◆ TEST() [276/399]

impeller::testing::TEST ( RectTest  ,
IRectEmptyDeclaration   
)

Definition at line 29 of file rect_unittests.cc.

29 {
30 IRect rect;
31
32 EXPECT_EQ(rect.GetLeft(), 0);
33 EXPECT_EQ(rect.GetTop(), 0);
34 EXPECT_EQ(rect.GetRight(), 0);
35 EXPECT_EQ(rect.GetBottom(), 0);
36 EXPECT_EQ(rect.GetX(), 0);
37 EXPECT_EQ(rect.GetY(), 0);
38 EXPECT_EQ(rect.GetWidth(), 0);
39 EXPECT_EQ(rect.GetHeight(), 0);
40 EXPECT_TRUE(rect.IsEmpty());
41 // EXPECT_TRUE(rect.IsFinite()); // should fail to compile
42}

◆ TEST() [277/399]

impeller::testing::TEST ( RectTest  ,
IRectExpand   
)

Definition at line 1238 of file rect_unittests.cc.

1238 {
1239 auto rect = IRect::MakeLTRB(100, 100, 200, 200);
1240
1241 // Expand(T amount)
1242 EXPECT_EQ(rect.Expand(10), IRect::MakeLTRB(90, 90, 210, 210));
1243 EXPECT_EQ(rect.Expand(-10), IRect::MakeLTRB(110, 110, 190, 190));
1244
1245 // Expand(amount, amount)
1246 EXPECT_EQ(rect.Expand(10, 10), IRect::MakeLTRB(90, 90, 210, 210));
1247 EXPECT_EQ(rect.Expand(10, -10), IRect::MakeLTRB(90, 110, 210, 190));
1248 EXPECT_EQ(rect.Expand(-10, 10), IRect::MakeLTRB(110, 90, 190, 210));
1249 EXPECT_EQ(rect.Expand(-10, -10), IRect::MakeLTRB(110, 110, 190, 190));
1250
1251 // Expand(amount, amount, amount, amount)
1252 EXPECT_EQ(rect.Expand(10, 20, 30, 40), IRect::MakeLTRB(90, 80, 230, 240));
1253 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), IRect::MakeLTRB(110, 80, 230, 240));
1254 EXPECT_EQ(rect.Expand(10, -20, 30, 40), IRect::MakeLTRB(90, 120, 230, 240));
1255 EXPECT_EQ(rect.Expand(10, 20, -30, 40), IRect::MakeLTRB(90, 80, 170, 240));
1256 EXPECT_EQ(rect.Expand(10, 20, 30, -40), IRect::MakeLTRB(90, 80, 230, 160));
1257
1258 // Expand(IPoint amount)
1259 EXPECT_EQ(rect.Expand(IPoint{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1260 EXPECT_EQ(rect.Expand(IPoint{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1261 EXPECT_EQ(rect.Expand(IPoint{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1262 EXPECT_EQ(rect.Expand(IPoint{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1263
1264 // Expand(ISize amount)
1265 EXPECT_EQ(rect.Expand(ISize{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1266 EXPECT_EQ(rect.Expand(ISize{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1267 EXPECT_EQ(rect.Expand(ISize{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1268 EXPECT_EQ(rect.Expand(ISize{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1269}

◆ TEST() [278/399]

impeller::testing::TEST ( RectTest  ,
IRectFromIRect   
)

Definition at line 616 of file rect_unittests.cc.

616 {
617 EXPECT_EQ(IRect(IRect::MakeXYWH(2, 3, 7, 15)), //
618 IRect::MakeXYWH(2, 3, 7, 15));
619 EXPECT_EQ(IRect(IRect::MakeLTRB(2, 3, 7, 15)), //
620 IRect::MakeLTRB(2, 3, 7, 15));
621}

◆ TEST() [279/399]

impeller::testing::TEST ( RectTest  ,
IRectGetNormalizingTransform   
)

Definition at line 1077 of file rect_unittests.cc.

1077 {
1078 {
1079 // Checks for expected matrix values
1080
1081 auto r = IRect::MakeXYWH(100, 200, 200, 400);
1082
1083 EXPECT_EQ(r.GetNormalizingTransform(),
1084 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1085 Matrix::MakeTranslation({-100, -200}));
1086 }
1087
1088 {
1089 // Checks for expected transform of points relative to the rect
1090
1091 auto r = IRect::MakeLTRB(300, 500, 400, 700);
1092 auto m = r.GetNormalizingTransform();
1093
1094 // The 4 corners of the rect => (0, 0) to (1, 1)
1095 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1096 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1097 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1098 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1099
1100 // The center => (0.5, 0.5)
1101 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1102
1103 // Outside the 4 corners => (-1, -1) to (2, 2)
1104 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1105 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1106 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1107 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1108 }
1109
1110 {
1111 // Checks for behavior with empty rects
1112
1113 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1114
1115 // Empty for width and/or height == 0
1116 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1117 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1118 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1119
1120 // Empty for width and/or height < 0
1121 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1122 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1123 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1124 }
1125}

◆ TEST() [280/399]

impeller::testing::TEST ( RectTest  ,
IRectIntersection   
)

Definition at line 1751 of file rect_unittests.cc.

1751 {
1752 auto check_empty_flips = [](const IRect& a, const IRect& b,
1753 const std::string& label) {
1754 ASSERT_FALSE(a.IsEmpty());
1755 // b is allowed to be empty
1756
1757 // unflipped a vs flipped (empty) b yields a
1758 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1759 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1760 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1761
1762 // flipped (empty) a vs unflipped b yields b
1763 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1764 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1765 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1766
1767 // flipped (empty) a vs flipped (empty) b yields empty
1768 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1769 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1770 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1771 };
1772
1773 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b,
1774 const IRect& result) {
1775 ASSERT_FALSE(a.IsEmpty()) << a;
1776 // b is allowed to be empty
1777
1778 std::stringstream stream;
1779 stream << a << " union " << b;
1780 auto label = stream.str();
1781
1782 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1783 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1784 EXPECT_EQ(a.Intersection(b), result) << label;
1785 EXPECT_EQ(b.Intersection(a), result) << label;
1786 check_empty_flips(a, b, label);
1787 };
1788
1789 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
1790 ASSERT_FALSE(a.IsEmpty()) << a;
1791 // b is allowed to be empty
1792
1793 std::stringstream stream;
1794 stream << a << " union " << b;
1795 auto label = stream.str();
1796
1797 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1798 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1799 check_empty_flips(a, b, label);
1800 };
1801
1802 {
1803 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1804 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1805
1806 test_empty(a, b);
1807 }
1808
1809 {
1810 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1811 auto b = IRect::MakeXYWH(10, 10, 0, 0);
1812
1813 test_empty(a, b);
1814 }
1815
1816 {
1817 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1818 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1819 auto expected = IRect::MakeXYWH(10, 10, 90, 90);
1820
1821 test_non_empty(a, b, expected);
1822 }
1823
1824 {
1825 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1826 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1827
1828 test_empty(a, b);
1829 }
1830
1831 {
1832 auto a = IRect::MakeMaximum();
1833 auto b = IRect::MakeXYWH(10, 10, 300, 300);
1834
1835 test_non_empty(a, b, b);
1836 }
1837
1838 {
1839 auto a = IRect::MakeMaximum();
1840 auto b = IRect::MakeMaximum();
1841
1842 test_non_empty(a, b, IRect::MakeMaximum());
1843 }
1844}
static void test_empty(skiatest::Reporter *reporter)

◆ TEST() [281/399]

impeller::testing::TEST ( RectTest  ,
IRectIntersectsWithRect   
)

Definition at line 2016 of file rect_unittests.cc.

2016 {
2017 auto check_empty_flips = [](const IRect& a, const IRect& b,
2018 const std::string& label) {
2019 ASSERT_FALSE(a.IsEmpty());
2020 // b is allowed to be empty
2021
2022 // unflipped a vs flipped (empty) b yields a
2023 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
2024 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
2025 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
2026
2027 // flipped (empty) a vs unflipped b yields b
2028 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
2029 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
2030 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
2031
2032 // flipped (empty) a vs flipped (empty) b yields empty
2033 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
2034 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
2035 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
2036 };
2037
2038 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2039 ASSERT_FALSE(a.IsEmpty()) << a;
2040 // b is allowed to be empty
2041
2042 std::stringstream stream;
2043 stream << a << " union " << b;
2044 auto label = stream.str();
2045
2046 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
2047 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
2048 check_empty_flips(a, b, label);
2049 };
2050
2051 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2052 ASSERT_FALSE(a.IsEmpty()) << a;
2053 // b is allowed to be empty
2054
2055 std::stringstream stream;
2056 stream << a << " union " << b;
2057 auto label = stream.str();
2058
2059 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
2060 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
2061 check_empty_flips(a, b, label);
2062 };
2063
2064 {
2065 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2066 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2067
2068 test_empty(a, b);
2069 }
2070
2071 {
2072 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2073 auto b = IRect::MakeXYWH(10, 10, 0, 0);
2074
2075 test_empty(a, b);
2076 }
2077
2078 {
2079 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2080 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2081
2082 test_non_empty(a, b);
2083 }
2084
2085 {
2086 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2087 auto b = IRect::MakeXYWH(100, 100, 100, 100);
2088
2089 test_empty(a, b);
2090 }
2091
2092 {
2093 auto a = IRect::MakeMaximum();
2094 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2095
2096 test_non_empty(a, b);
2097 }
2098
2099 {
2100 auto a = IRect::MakeMaximum();
2101 auto b = IRect::MakeMaximum();
2102
2103 test_non_empty(a, b);
2104 }
2105}

◆ TEST() [282/399]

impeller::testing::TEST ( RectTest  ,
IRectMakeMaximum   
)

Definition at line 593 of file rect_unittests.cc.

593 {
594 IRect rect = IRect::MakeMaximum();
595 auto min = std::numeric_limits<int64_t>::min();
596 auto max = std::numeric_limits<int64_t>::max();
597
598 EXPECT_EQ(rect.GetLeft(), min);
599 EXPECT_EQ(rect.GetTop(), min);
600 EXPECT_EQ(rect.GetRight(), max);
601 EXPECT_EQ(rect.GetBottom(), max);
602 EXPECT_EQ(rect.GetX(), min);
603 EXPECT_EQ(rect.GetY(), min);
604 EXPECT_EQ(rect.GetWidth(), max);
605 EXPECT_EQ(rect.GetHeight(), max);
606 EXPECT_FALSE(rect.IsEmpty());
607}
static float max(float r, float g, float b)
Definition hsl.cpp:49
static float min(float r, float g, float b)
Definition hsl.cpp:48

◆ TEST() [283/399]

impeller::testing::TEST ( RectTest  ,
IRectOriginSizeXYWHGetters   
)

Definition at line 683 of file rect_unittests.cc.

683 {
684 {
685 IRect r = IRect::MakeOriginSize({10, 20}, {50, 40});
686 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
687 EXPECT_EQ(r.GetSize(), ISize(50, 40));
688 EXPECT_EQ(r.GetX(), 10);
689 EXPECT_EQ(r.GetY(), 20);
690 EXPECT_EQ(r.GetWidth(), 50);
691 EXPECT_EQ(r.GetHeight(), 40);
692 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
693 EXPECT_EQ(r.GetXYWH(), expected_array);
694 }
695
696 {
697 IRect r = IRect::MakeLTRB(10, 20, 50, 40);
698 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
699 EXPECT_EQ(r.GetSize(), ISize(40, 20));
700 EXPECT_EQ(r.GetX(), 10);
701 EXPECT_EQ(r.GetY(), 20);
702 EXPECT_EQ(r.GetWidth(), 40);
703 EXPECT_EQ(r.GetHeight(), 20);
704 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
705 EXPECT_EQ(r.GetXYWH(), expected_array);
706 }
707}
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
Definition rect.h:304
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Definition rect.h:294
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition rect.h:314
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition rect.h:300
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition rect.h:308
constexpr std::array< T, 4 > GetXYWH() const
Get the x, y coordinates of the origin and the width and height of the rectangle in an array.
Definition rect.h:361
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
Definition rect.h:287

◆ TEST() [284/399]

impeller::testing::TEST ( RectTest  ,
IRectOverflowLTRB   
)

Definition at line 478 of file rect_unittests.cc.

478 {
479 auto min = std::numeric_limits<int64_t>::min();
480 auto max = std::numeric_limits<int64_t>::max();
481
482 // 4 cases
483 // negative l, r near max takes width past max
484 // positive l, r near min takes width below min
485 // negative t, b near max takes width past max
486 // positive t, b near min takes width below min
487
488 {
489 IRect rect = IRect::MakeLTRB(-10, 10, max - 5, 26);
490
491 EXPECT_EQ(rect.GetLeft(), -10);
492 EXPECT_EQ(rect.GetTop(), 10);
493 EXPECT_EQ(rect.GetRight(), max - 5);
494 EXPECT_EQ(rect.GetBottom(), 26);
495 EXPECT_EQ(rect.GetX(), -10);
496 EXPECT_EQ(rect.GetY(), 10);
497 EXPECT_EQ(rect.GetWidth(), max);
498 EXPECT_EQ(rect.GetHeight(), 16);
499 EXPECT_FALSE(rect.IsEmpty());
500 }
501
502 {
503 IRect rect = IRect::MakeLTRB(10, 10, min + 5, 26);
504
505 EXPECT_EQ(rect.GetLeft(), 10);
506 EXPECT_EQ(rect.GetTop(), 10);
507 EXPECT_EQ(rect.GetRight(), min + 5);
508 EXPECT_EQ(rect.GetBottom(), 26);
509 EXPECT_EQ(rect.GetX(), 10);
510 EXPECT_EQ(rect.GetY(), 10);
511 EXPECT_EQ(rect.GetWidth(), min);
512 EXPECT_EQ(rect.GetHeight(), 16);
513 EXPECT_TRUE(rect.IsEmpty());
514 }
515
516 {
517 IRect rect = IRect::MakeLTRB(5, -10, 15, max - 5);
518
519 EXPECT_EQ(rect.GetLeft(), 5);
520 EXPECT_EQ(rect.GetTop(), -10);
521 EXPECT_EQ(rect.GetRight(), 15);
522 EXPECT_EQ(rect.GetBottom(), max - 5);
523 EXPECT_EQ(rect.GetX(), 5);
524 EXPECT_EQ(rect.GetY(), -10);
525 EXPECT_EQ(rect.GetWidth(), 10);
526 EXPECT_EQ(rect.GetHeight(), max);
527 EXPECT_FALSE(rect.IsEmpty());
528 }
529
530 {
531 IRect rect = IRect::MakeLTRB(5, 10, 15, min + 5);
532
533 EXPECT_EQ(rect.GetLeft(), 5);
534 EXPECT_EQ(rect.GetTop(), 10);
535 EXPECT_EQ(rect.GetRight(), 15);
536 EXPECT_EQ(rect.GetBottom(), min + 5);
537 EXPECT_EQ(rect.GetX(), 5);
538 EXPECT_EQ(rect.GetY(), 10);
539 EXPECT_EQ(rect.GetWidth(), 10);
540 EXPECT_EQ(rect.GetHeight(), min);
541 EXPECT_TRUE(rect.IsEmpty());
542 }
543}
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350

◆ TEST() [285/399]

impeller::testing::TEST ( RectTest  ,
IRectOverflowXYWH   
)

Definition at line 272 of file rect_unittests.cc.

272 {
273 auto min = std::numeric_limits<int64_t>::min();
274 auto max = std::numeric_limits<int64_t>::max();
275
276 // 4 cases
277 // x near max, positive w takes it past max
278 // x near min, negative w takes it below min
279 // y near max, positive h takes it past max
280 // y near min, negative h takes it below min
281
282 {
283 IRect rect = IRect::MakeXYWH(max - 5, 10, 10, 16);
284
285 EXPECT_EQ(rect.GetLeft(), max - 5);
286 EXPECT_EQ(rect.GetTop(), 10);
287 EXPECT_EQ(rect.GetRight(), max);
288 EXPECT_EQ(rect.GetBottom(), 26);
289 EXPECT_EQ(rect.GetX(), max - 5);
290 EXPECT_EQ(rect.GetY(), 10);
291 EXPECT_EQ(rect.GetWidth(), 5);
292 EXPECT_EQ(rect.GetHeight(), 16);
293 EXPECT_FALSE(rect.IsEmpty());
294 }
295
296 {
297 IRect rect = IRect::MakeXYWH(min + 5, 10, -10, 16);
298
299 EXPECT_EQ(rect.GetLeft(), min + 5);
300 EXPECT_EQ(rect.GetTop(), 10);
301 EXPECT_EQ(rect.GetRight(), min);
302 EXPECT_EQ(rect.GetBottom(), 26);
303 EXPECT_EQ(rect.GetX(), min + 5);
304 EXPECT_EQ(rect.GetY(), 10);
305 EXPECT_EQ(rect.GetWidth(), -5);
306 EXPECT_EQ(rect.GetHeight(), 16);
307 EXPECT_TRUE(rect.IsEmpty());
308 }
309
310 {
311 IRect rect = IRect::MakeXYWH(5, max - 10, 10, 16);
312
313 EXPECT_EQ(rect.GetLeft(), 5);
314 EXPECT_EQ(rect.GetTop(), max - 10);
315 EXPECT_EQ(rect.GetRight(), 15);
316 EXPECT_EQ(rect.GetBottom(), max);
317 EXPECT_EQ(rect.GetX(), 5);
318 EXPECT_EQ(rect.GetY(), max - 10);
319 EXPECT_EQ(rect.GetWidth(), 10);
320 EXPECT_EQ(rect.GetHeight(), 10);
321 EXPECT_FALSE(rect.IsEmpty());
322 }
323
324 {
325 IRect rect = IRect::MakeXYWH(5, min + 10, 10, -16);
326
327 EXPECT_EQ(rect.GetLeft(), 5);
328 EXPECT_EQ(rect.GetTop(), min + 10);
329 EXPECT_EQ(rect.GetRight(), 15);
330 EXPECT_EQ(rect.GetBottom(), min);
331 EXPECT_EQ(rect.GetX(), 5);
332 EXPECT_EQ(rect.GetY(), min + 10);
333 EXPECT_EQ(rect.GetWidth(), 10);
334 EXPECT_EQ(rect.GetHeight(), -10);
335 EXPECT_TRUE(rect.IsEmpty());
336 }
337}

◆ TEST() [286/399]

impeller::testing::TEST ( RectTest  ,
IRectRound   
)

Definition at line 2880 of file rect_unittests.cc.

2880 {
2881 {
2882 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
2883 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
2884 EXPECT_EQ(IRect::Round(r), ir);
2885 }
2886 {
2887 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
2888 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
2889 EXPECT_EQ(IRect::Round(r), ir);
2890 }
2891 {
2892 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
2893 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
2894 EXPECT_EQ(IRect::Round(r), ir);
2895 }
2896}

◆ TEST() [287/399]

impeller::testing::TEST ( RectTest  ,
IRectRoundOut   
)

Definition at line 2852 of file rect_unittests.cc.

2852 {
2853 {
2854 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
2855 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
2856 EXPECT_EQ(IRect::RoundOut(r), ir);
2857 }
2858 {
2859 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
2860 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
2861 EXPECT_EQ(IRect::RoundOut(r), ir);
2862 }
2863}

◆ TEST() [288/399]

impeller::testing::TEST ( RectTest  ,
IRectScale   
)

Definition at line 929 of file rect_unittests.cc.

929 {
930 auto test1 = [](IRect rect, int64_t scale) {
931 IRect expected = IRect::MakeXYWH(rect.GetX() * scale, //
932 rect.GetY() * scale, //
933 rect.GetWidth() * scale, //
934 rect.GetHeight() * scale);
935
936 EXPECT_EQ(rect.Scale(scale), expected) //
937 << rect << " * " << scale;
938 EXPECT_EQ(rect.Scale(scale, scale), expected) //
939 << rect << " * " << scale;
940 EXPECT_EQ(rect.Scale(IPoint(scale, scale)), expected) //
941 << rect << " * " << scale;
942 EXPECT_EQ(rect.Scale(ISize(scale, scale)), expected) //
943 << rect << " * " << scale;
944 };
945
946 auto test2 = [&test1](IRect rect, int64_t scale_x, int64_t scale_y) {
947 IRect expected = IRect::MakeXYWH(rect.GetX() * scale_x, //
948 rect.GetY() * scale_y, //
949 rect.GetWidth() * scale_x, //
950 rect.GetHeight() * scale_y);
951
952 EXPECT_EQ(rect.Scale(scale_x, scale_y), expected) //
953 << rect << " * " << scale_x << ", " << scale_y;
954 EXPECT_EQ(rect.Scale(IPoint(scale_x, scale_y)), expected) //
955 << rect << " * " << scale_x << ", " << scale_y;
956 EXPECT_EQ(rect.Scale(ISize(scale_x, scale_y)), expected) //
957 << rect << " * " << scale_x << ", " << scale_y;
958
959 test1(rect, scale_x);
960 test1(rect, scale_y);
961 };
962
963 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, 3);
964 test2(IRect::MakeLTRB(10, 15, 100, 150), 3, 2);
965 test2(IRect::MakeLTRB(10, 15, -100, 150), 2, 3);
966 test2(IRect::MakeLTRB(10, 15, 100, -150), 2, 3);
967 test2(IRect::MakeLTRB(10, 15, 100, 150), -2, 3);
968 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, -3);
969}
static void test1(skiatest::Reporter *reporter, SkWriter32 *writer)

◆ TEST() [289/399]

impeller::testing::TEST ( RectTest  ,
IRectSimpleLTRB   
)

Definition at line 89 of file rect_unittests.cc.

89 {
90 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
91
92 EXPECT_EQ(rect.GetLeft(), 5);
93 EXPECT_EQ(rect.GetTop(), 10);
94 EXPECT_EQ(rect.GetRight(), 20);
95 EXPECT_EQ(rect.GetBottom(), 25);
96 EXPECT_EQ(rect.GetX(), 5);
97 EXPECT_EQ(rect.GetY(), 10);
98 EXPECT_EQ(rect.GetWidth(), 15);
99 EXPECT_EQ(rect.GetHeight(), 15);
100 EXPECT_FALSE(rect.IsEmpty());
101}

◆ TEST() [290/399]

impeller::testing::TEST ( RectTest  ,
IRectSimpleXYWH   
)

Definition at line 119 of file rect_unittests.cc.

119 {
120 IRect rect = IRect::MakeXYWH(5, 10, 15, 16);
121
122 EXPECT_EQ(rect.GetLeft(), 5);
123 EXPECT_EQ(rect.GetTop(), 10);
124 EXPECT_EQ(rect.GetRight(), 20);
125 EXPECT_EQ(rect.GetBottom(), 26);
126 EXPECT_EQ(rect.GetX(), 5);
127 EXPECT_EQ(rect.GetY(), 10);
128 EXPECT_EQ(rect.GetWidth(), 15);
129 EXPECT_EQ(rect.GetHeight(), 16);
130 EXPECT_FALSE(rect.IsEmpty());
131}

◆ TEST() [291/399]

impeller::testing::TEST ( RectTest  ,
IRectUnion   
)

Definition at line 1456 of file rect_unittests.cc.

1456 {
1457 auto check_empty_flips = [](const IRect& a, const IRect& b,
1458 const std::string& label) {
1459 ASSERT_FALSE(a.IsEmpty());
1460 // b is allowed to be empty
1461
1462 // unflipped a vs flipped (empty) b yields a
1463 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1464 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1465 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1466
1467 // flipped (empty) a vs unflipped b yields b
1468 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1469 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1470 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1471
1472 // flipped (empty) a vs flipped (empty) b yields empty
1473 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1474 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1475 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1476 };
1477
1478 auto test = [&check_empty_flips](const IRect& a, const IRect& b,
1479 const IRect& result) {
1480 ASSERT_FALSE(a.IsEmpty()) << a;
1481 // b is allowed to be empty
1482
1483 std::stringstream stream;
1484 stream << a << " union " << b;
1485 auto label = stream.str();
1486
1487 EXPECT_EQ(a.Union(b), result) << label;
1488 EXPECT_EQ(b.Union(a), result) << label;
1489 check_empty_flips(a, b, label);
1490 };
1491
1492 {
1493 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1494 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1495 auto expected = IRect::MakeXYWH(100, 100, 100, 100);
1496 test(a, b, expected);
1497 }
1498
1499 {
1500 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1501 auto b = IRect::MakeXYWH(0, 0, 1, 1);
1502 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1503 test(a, b, expected);
1504 }
1505
1506 {
1507 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1508 auto b = IRect::MakeXYWH(10, 10, 1, 1);
1509 auto expected = IRect::MakeXYWH(10, 10, 190, 190);
1510 test(a, b, expected);
1511 }
1512
1513 {
1514 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1515 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1516 auto expected = IRect::MakeXYWH(0, 0, 110, 110);
1517 test(a, b, expected);
1518 }
1519
1520 {
1521 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1522 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1523 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1524 test(a, b, expected);
1525 }
1526}
static void Union(SkRegion *rgn, const SkIRect &rect)

◆ TEST() [292/399]

impeller::testing::TEST ( RectTest  ,
IRectXYWHIsEmpty   
)

Definition at line 1151 of file rect_unittests.cc.

1151 {
1152 // Non-empty
1153 EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
1154
1155 // Empty both width and height both 0 or negative, in all combinations
1156 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
1157 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
1158 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
1159 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
1160
1161 // Empty for 0 or negative width or height (but not both at the same time)
1162 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
1163 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
1164 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
1165 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
1166}

◆ TEST() [293/399]

impeller::testing::TEST ( RectTest  ,
IsSquare   
)

Definition at line 1182 of file rect_unittests.cc.

1182 {
1183 EXPECT_TRUE(Rect::MakeXYWH(10, 30, 20, 20).IsSquare());
1184 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 20, 19).IsSquare());
1185 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 19, 20).IsSquare());
1186 EXPECT_TRUE(Rect::MakeMaximum().IsSquare());
1187
1188 EXPECT_TRUE(IRect::MakeXYWH(10, 30, 20, 20).IsSquare());
1189 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 20, 19).IsSquare());
1190 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 19, 20).IsSquare());
1191 EXPECT_TRUE(IRect::MakeMaximum().IsSquare());
1192}

◆ TEST() [294/399]

impeller::testing::TEST ( RectTest  ,
MakePointBoundsQuad   
)

Definition at line 1168 of file rect_unittests.cc.

1168 {
1169 Quad quad = {
1170 Point(10, 10),
1171 Point(20, 10),
1172 Point(10, 20),
1173 Point(20, 20),
1174 };
1175 std::optional<Rect> bounds = Rect::MakePointBounds(quad);
1176 EXPECT_TRUE(bounds.has_value());
1177 if (bounds.has_value()) {
1178 EXPECT_TRUE(RectNear(bounds.value(), Rect::MakeLTRB(10, 10, 20, 20)));
1179 }
1180}
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
std::array< Point, 4 > Quad
Definition point.h:321

◆ TEST() [295/399]

impeller::testing::TEST ( RectTest  ,
OptIRectIntersection   
)

Definition at line 1846 of file rect_unittests.cc.

1846 {
1847 auto a = IRect::MakeLTRB(0, 0, 110, 110);
1848 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1849 auto c = IRect::MakeLTRB(100, 0, 200, 110);
1850
1851 // NullOpt, NullOpt
1852 EXPECT_FALSE(IRect::Intersection(std::nullopt, std::nullopt).has_value());
1853 EXPECT_EQ(IRect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1854
1855 auto test1 = [](const IRect& r) {
1856 // Rect, NullOpt
1857 EXPECT_TRUE(IRect::Intersection(r, std::nullopt).has_value());
1858 EXPECT_EQ(IRect::Intersection(r, std::nullopt).value(), r);
1859
1860 // OptRect, NullOpt
1862 IRect::Intersection(std::optional(r), std::nullopt).has_value());
1863 EXPECT_EQ(IRect::Intersection(std::optional(r), std::nullopt).value(), r);
1864
1865 // NullOpt, Rect
1866 EXPECT_TRUE(IRect::Intersection(std::nullopt, r).has_value());
1867 EXPECT_EQ(IRect::Intersection(std::nullopt, r).value(), r);
1868
1869 // NullOpt, OptRect
1871 IRect::Intersection(std::nullopt, std::optional(r)).has_value());
1872 EXPECT_EQ(IRect::Intersection(std::nullopt, std::optional(r)).value(), r);
1873 };
1874
1875 test1(a);
1876 test1(b);
1877 test1(c);
1878
1879 auto test2 = [](const IRect& a, const IRect& b, const IRect& i) {
1880 ASSERT_EQ(a.Intersection(b), i);
1881
1882 // Rect, OptRect
1883 EXPECT_TRUE(IRect::Intersection(a, std::optional(b)).has_value());
1884 EXPECT_EQ(IRect::Intersection(a, std::optional(b)).value(), i);
1885
1886 // OptRect, Rect
1887 EXPECT_TRUE(IRect::Intersection(std::optional(a), b).has_value());
1888 EXPECT_EQ(IRect::Intersection(std::optional(a), b).value(), i);
1889
1890 // OptRect, OptRect
1892 IRect::Intersection(std::optional(a), std::optional(b)).has_value());
1893 EXPECT_EQ(IRect::Intersection(std::optional(a), std::optional(b)).value(),
1894 i);
1895 };
1896
1897 test2(a, b, IRect::MakeLTRB(100, 100, 110, 110));
1898 test2(a, c, IRect::MakeLTRB(100, 0, 110, 110));
1899 test2(b, c, IRect::MakeLTRB(100, 100, 200, 110));
1900}

◆ TEST() [296/399]

impeller::testing::TEST ( RectTest  ,
OptIRectUnion   
)

Definition at line 1528 of file rect_unittests.cc.

1528 {
1529 auto a = IRect::MakeLTRB(0, 0, 100, 100);
1530 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1531 auto c = IRect::MakeLTRB(100, 0, 200, 100);
1532
1533 // NullOpt, NullOpt
1534 EXPECT_FALSE(IRect::Union(std::nullopt, std::nullopt).has_value());
1535 EXPECT_EQ(IRect::Union(std::nullopt, std::nullopt), std::nullopt);
1536
1537 auto test1 = [](const IRect& r) {
1538 // Rect, NullOpt
1539 EXPECT_TRUE(IRect::Union(r, std::nullopt).has_value());
1540 EXPECT_EQ(IRect::Union(r, std::nullopt).value(), r);
1541
1542 // OptRect, NullOpt
1543 EXPECT_TRUE(IRect::Union(std::optional(r), std::nullopt).has_value());
1544 EXPECT_EQ(IRect::Union(std::optional(r), std::nullopt).value(), r);
1545
1546 // NullOpt, Rect
1547 EXPECT_TRUE(IRect::Union(std::nullopt, r).has_value());
1548 EXPECT_EQ(IRect::Union(std::nullopt, r).value(), r);
1549
1550 // NullOpt, OptRect
1551 EXPECT_TRUE(IRect::Union(std::nullopt, std::optional(r)).has_value());
1552 EXPECT_EQ(IRect::Union(std::nullopt, std::optional(r)).value(), r);
1553 };
1554
1555 test1(a);
1556 test1(b);
1557 test1(c);
1558
1559 auto test2 = [](const IRect& a, const IRect& b, const IRect& u) {
1560 ASSERT_EQ(a.Union(b), u);
1561
1562 // Rect, OptRect
1563 EXPECT_TRUE(IRect::Union(a, std::optional(b)).has_value());
1564 EXPECT_EQ(IRect::Union(a, std::optional(b)).value(), u);
1565
1566 // OptRect, Rect
1567 EXPECT_TRUE(IRect::Union(std::optional(a), b).has_value());
1568 EXPECT_EQ(IRect::Union(std::optional(a), b).value(), u);
1569
1570 // OptRect, OptRect
1571 EXPECT_TRUE(IRect::Union(std::optional(a), std::optional(b)).has_value());
1572 EXPECT_EQ(IRect::Union(std::optional(a), std::optional(b)).value(), u);
1573 };
1574
1575 test2(a, b, IRect::MakeLTRB(0, 0, 200, 200));
1576 test2(a, c, IRect::MakeLTRB(0, 0, 200, 100));
1577 test2(b, c, IRect::MakeLTRB(100, 0, 200, 200));
1578}

◆ TEST() [297/399]

impeller::testing::TEST ( RectTest  ,
OptRectIntersection   
)

Definition at line 1697 of file rect_unittests.cc.

1697 {
1698 auto a = Rect::MakeLTRB(0, 0, 110, 110);
1699 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1700 auto c = Rect::MakeLTRB(100, 0, 200, 110);
1701
1702 // NullOpt, NullOpt
1703 EXPECT_FALSE(Rect::Intersection(std::nullopt, std::nullopt).has_value());
1704 EXPECT_EQ(Rect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1705
1706 auto test1 = [](const Rect& r) {
1707 // Rect, NullOpt
1708 EXPECT_TRUE(Rect::Intersection(r, std::nullopt).has_value());
1709 EXPECT_EQ(Rect::Intersection(r, std::nullopt).value(), r);
1710
1711 // OptRect, NullOpt
1712 EXPECT_TRUE(Rect::Intersection(std::optional(r), std::nullopt).has_value());
1713 EXPECT_EQ(Rect::Intersection(std::optional(r), std::nullopt).value(), r);
1714
1715 // NullOpt, Rect
1716 EXPECT_TRUE(Rect::Intersection(std::nullopt, r).has_value());
1717 EXPECT_EQ(Rect::Intersection(std::nullopt, r).value(), r);
1718
1719 // NullOpt, OptRect
1720 EXPECT_TRUE(Rect::Intersection(std::nullopt, std::optional(r)).has_value());
1721 EXPECT_EQ(Rect::Intersection(std::nullopt, std::optional(r)).value(), r);
1722 };
1723
1724 test1(a);
1725 test1(b);
1726 test1(c);
1727
1728 auto test2 = [](const Rect& a, const Rect& b, const Rect& i) {
1729 ASSERT_EQ(a.Intersection(b), i);
1730
1731 // Rect, OptRect
1732 EXPECT_TRUE(Rect::Intersection(a, std::optional(b)).has_value());
1733 EXPECT_EQ(Rect::Intersection(a, std::optional(b)).value(), i);
1734
1735 // OptRect, Rect
1736 EXPECT_TRUE(Rect::Intersection(std::optional(a), b).has_value());
1737 EXPECT_EQ(Rect::Intersection(std::optional(a), b).value(), i);
1738
1739 // OptRect, OptRect
1741 Rect::Intersection(std::optional(a), std::optional(b)).has_value());
1742 EXPECT_EQ(Rect::Intersection(std::optional(a), std::optional(b)).value(),
1743 i);
1744 };
1745
1746 test2(a, b, Rect::MakeLTRB(100, 100, 110, 110));
1747 test2(a, c, Rect::MakeLTRB(100, 0, 110, 110));
1748 test2(b, c, Rect::MakeLTRB(100, 100, 200, 110));
1749}

◆ TEST() [298/399]

impeller::testing::TEST ( RectTest  ,
OptRectUnion   
)

Definition at line 1404 of file rect_unittests.cc.

1404 {
1405 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1406 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1407 auto c = Rect::MakeLTRB(100, 0, 200, 100);
1408
1409 // NullOpt, NullOpt
1410 EXPECT_FALSE(Rect::Union(std::nullopt, std::nullopt).has_value());
1411 EXPECT_EQ(Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1412
1413 auto test1 = [](const Rect& r) {
1414 // Rect, NullOpt
1415 EXPECT_TRUE(Rect::Union(r, std::nullopt).has_value());
1416 EXPECT_EQ(Rect::Union(r, std::nullopt).value(), r);
1417
1418 // OptRect, NullOpt
1419 EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
1420 EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
1421
1422 // NullOpt, Rect
1423 EXPECT_TRUE(Rect::Union(std::nullopt, r).has_value());
1424 EXPECT_EQ(Rect::Union(std::nullopt, r).value(), r);
1425
1426 // NullOpt, OptRect
1427 EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
1428 EXPECT_EQ(Rect::Union(std::nullopt, std::optional(r)).value(), r);
1429 };
1430
1431 test1(a);
1432 test1(b);
1433 test1(c);
1434
1435 auto test2 = [](const Rect& a, const Rect& b, const Rect& u) {
1436 ASSERT_EQ(a.Union(b), u);
1437
1438 // Rect, OptRect
1439 EXPECT_TRUE(Rect::Union(a, std::optional(b)).has_value());
1440 EXPECT_EQ(Rect::Union(a, std::optional(b)).value(), u);
1441
1442 // OptRect, Rect
1443 EXPECT_TRUE(Rect::Union(std::optional(a), b).has_value());
1444 EXPECT_EQ(Rect::Union(std::optional(a), b).value(), u);
1445
1446 // OptRect, OptRect
1447 EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
1448 EXPECT_EQ(Rect::Union(std::optional(a), std::optional(b)).value(), u);
1449 };
1450
1451 test2(a, b, Rect::MakeLTRB(0, 0, 200, 200));
1452 test2(a, c, Rect::MakeLTRB(0, 0, 200, 100));
1453 test2(b, c, Rect::MakeLTRB(100, 0, 200, 200));
1454}

◆ TEST() [299/399]

impeller::testing::TEST ( RectTest  ,
RectArea   
)

Definition at line 971 of file rect_unittests.cc.

971 {
972 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
973 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
974 EXPECT_EQ(Rect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
975 EXPECT_EQ(Rect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
976 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
977 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
978}

◆ TEST() [300/399]

impeller::testing::TEST ( RectTest  ,
RectContainsPoint   
)

Definition at line 2107 of file rect_unittests.cc.

2107 {
2108 auto check_nans = [](const Rect& rect, const Point& point,
2109 const std::string& label) {
2110 ASSERT_TRUE(rect.IsFinite()) << label;
2111 ASSERT_TRUE(point.IsFinite()) << label;
2112
2113 for (int i = 1; i < 16; i++) {
2114 EXPECT_FALSE(swap_nan(rect, i).Contains(point))
2115 << label << ", index = " << i;
2116 for (int j = 1; j < 4; j++) {
2117 EXPECT_FALSE(swap_nan(rect, i).Contains(swap_nan(point, j)))
2118 << label << ", indices = " << i << ", " << j;
2119 }
2120 }
2121 };
2122
2123 auto check_empty_flips = [](const Rect& rect, const Point& point,
2124 const std::string& label) {
2125 ASSERT_FALSE(rect.IsEmpty());
2126
2127 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2128 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2129 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2130 };
2131
2132 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2133 const Point& point) {
2134 ASSERT_FALSE(rect.IsEmpty()) << rect;
2135
2136 std::stringstream stream;
2137 stream << rect << " contains " << point;
2138 auto label = stream.str();
2139
2140 EXPECT_TRUE(rect.Contains(point)) << label;
2141 check_empty_flips(rect, point, label);
2142 check_nans(rect, point, label);
2143 };
2144
2145 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2146 const Point& point) {
2147 ASSERT_FALSE(rect.IsEmpty()) << rect;
2148
2149 std::stringstream stream;
2150 stream << rect << " contains " << point;
2151 auto label = stream.str();
2152
2153 EXPECT_FALSE(rect.Contains(point)) << label;
2154 check_empty_flips(rect, point, label);
2155 check_nans(rect, point, label);
2156 };
2157
2158 {
2159 // Origin is inclusive
2160 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2161 auto p = Point(100, 100);
2162
2163 test_inside(r, p);
2164 }
2165 {
2166 // Size is exclusive
2167 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2168 auto p = Point(200, 200);
2169
2170 test_outside(r, p);
2171 }
2172 {
2173 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2174 auto p = Point(99, 99);
2175
2176 test_outside(r, p);
2177 }
2178 {
2179 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2180 auto p = Point(199, 199);
2181
2182 test_inside(r, p);
2183 }
2184
2185 {
2186 auto r = Rect::MakeMaximum();
2187 auto p = Point(199, 199);
2188
2189 test_inside(r, p);
2190 }
2191}
bool Contains(const Container &container, const Value &value)
static constexpr Rect swap_nan(const Rect &rect, int index)

◆ TEST() [301/399]

impeller::testing::TEST ( RectTest  ,
RectContainsRect   
)

Definition at line 2262 of file rect_unittests.cc.

2262 {
2263 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
2264 ASSERT_TRUE(a.IsFinite()) << label;
2265 ASSERT_TRUE(b.IsFinite()) << label;
2266 ASSERT_FALSE(a.IsEmpty());
2267
2268 for (int i = 1; i < 16; i++) {
2269 // NaN in a produces false
2270 EXPECT_FALSE(swap_nan(a, i).Contains(b)) << label << ", index = " << i;
2271 // NaN in b produces false
2272 EXPECT_TRUE(a.Contains(swap_nan(b, i))) << label << ", index = " << i;
2273 // NaN in both is false
2274 for (int j = 1; j < 16; j++) {
2275 EXPECT_FALSE(swap_nan(a, i).Contains(swap_nan(b, j)))
2276 << label << ", indices = " << i << ", " << j;
2277 }
2278 }
2279 };
2280
2281 auto check_empty_flips = [](const Rect& a, const Rect& b,
2282 const std::string& label) {
2283 ASSERT_FALSE(a.IsEmpty());
2284 // test b rects are allowed to have 0 w/h, but not be backwards
2285 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2286
2287 // unflipped a vs flipped (empty) b yields false
2288 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2289 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2290 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2291
2292 // flipped (empty) a vs unflipped b yields false
2293 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2294 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2295 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2296
2297 // flipped (empty) a vs flipped (empty) b yields empty
2298 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2299 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2300 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2301 };
2302
2303 auto test_inside = [&check_nans, &check_empty_flips](const Rect& a,
2304 const Rect& b) {
2305 ASSERT_FALSE(a.IsEmpty()) << a;
2306 // test b rects are allowed to have 0 w/h, but not be backwards
2307 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2308
2309 std::stringstream stream;
2310 stream << a << " contains " << b;
2311 auto label = stream.str();
2312
2313 EXPECT_TRUE(a.Contains(b)) << label;
2314 check_empty_flips(a, b, label);
2315 check_nans(a, b, label);
2316 };
2317
2318 auto test_not_inside = [&check_nans, &check_empty_flips](const Rect& a,
2319 const Rect& b) {
2320 ASSERT_FALSE(a.IsEmpty()) << a;
2321 // If b was empty, it would be contained and should not be tested with
2322 // this function - use |test_inside| instead.
2323 ASSERT_FALSE(b.IsEmpty()) << b;
2324
2325 std::stringstream stream;
2326 stream << a << " contains " << b;
2327 auto label = stream.str();
2328
2329 EXPECT_FALSE(a.Contains(b)) << label;
2330 check_empty_flips(a, b, label);
2331 check_nans(a, b, label);
2332 };
2333
2334 {
2335 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2336
2337 test_inside(a, a);
2338 }
2339 {
2340 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2341 auto b = Rect::MakeXYWH(0, 0, 0, 0);
2342
2343 test_inside(a, b);
2344 }
2345 {
2346 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2347 auto b = Rect::MakeXYWH(150, 150, 20, 20);
2348
2349 test_inside(a, b);
2350 }
2351 {
2352 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2353 auto b = Rect::MakeXYWH(150, 150, 100, 100);
2354
2355 test_not_inside(a, b);
2356 }
2357 {
2358 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2359 auto b = Rect::MakeXYWH(50, 50, 100, 100);
2360
2361 test_not_inside(a, b);
2362 }
2363 {
2364 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2365 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2366
2367 test_not_inside(a, b);
2368 }
2369 {
2370 auto a = Rect::MakeMaximum();
2371 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2372
2373 test_inside(a, b);
2374 }
2375}

◆ TEST() [302/399]

impeller::testing::TEST ( RectTest  ,
RectCopy   
)

Definition at line 623 of file rect_unittests.cc.

623 {
624 // Using fractional-power-of-2 friendly values for equality tests
625 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
626 Rect copy = rect;
627
628 EXPECT_EQ(rect, copy);
629 EXPECT_EQ(copy.GetLeft(), 5.125f);
630 EXPECT_EQ(copy.GetTop(), 10.25f);
631 EXPECT_EQ(copy.GetRight(), 20.625f);
632 EXPECT_EQ(copy.GetBottom(), 25.375f);
633 EXPECT_EQ(copy.GetX(), 5.125f);
634 EXPECT_EQ(copy.GetY(), 10.25f);
635 EXPECT_EQ(copy.GetWidth(), 15.5f);
636 EXPECT_EQ(copy.GetHeight(), 15.125f);
637 EXPECT_FALSE(copy.IsEmpty());
638 EXPECT_TRUE(copy.IsFinite());
639}

◆ TEST() [303/399]

impeller::testing::TEST ( RectTest  ,
RectCutOut   
)

Definition at line 2470 of file rect_unittests.cc.

2470 {
2471 Rect cull_rect = Rect::MakeLTRB(20, 20, 40, 40);
2472
2473 auto check_nans = [&cull_rect](const Rect& diff_rect,
2474 const std::string& label) {
2475 EXPECT_TRUE(cull_rect.IsFinite()) << label;
2476 EXPECT_TRUE(diff_rect.IsFinite()) << label;
2477
2478 for (int i = 1; i < 16; i++) {
2479 // NaN in cull_rect produces empty
2480 EXPECT_FALSE(swap_nan(cull_rect, i).Cutout(diff_rect).has_value())
2481 << label << ", index " << i;
2482 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(diff_rect), Rect())
2483 << label << ", index " << i;
2484
2485 // NaN in diff_rect is nop
2486 EXPECT_TRUE(cull_rect.Cutout(swap_nan(diff_rect, i)).has_value())
2487 << label << ", index " << i;
2488 EXPECT_EQ(cull_rect.CutoutOrEmpty(swap_nan(diff_rect, i)), cull_rect)
2489 << label << ", index " << i;
2490
2491 for (int j = 1; j < 16; j++) {
2492 // NaN in both is also empty
2493 EXPECT_FALSE(
2494 swap_nan(cull_rect, i).Cutout(swap_nan(diff_rect, j)).has_value())
2495 << label << ", indices " << i << ", " << j;
2496 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(swap_nan(diff_rect, j)),
2497 Rect())
2498 << label << ", indices " << i << ", " << j;
2499 }
2500 }
2501 };
2502
2503 auto check_empty_flips = [&cull_rect](const Rect& diff_rect,
2504 const std::string& label) {
2505 EXPECT_FALSE(cull_rect.IsEmpty()) << label;
2506 EXPECT_FALSE(diff_rect.IsEmpty()) << label;
2507
2508 // unflipped cull_rect vs flipped(empty) diff_rect
2509 // == cull_rect
2510 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2511 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2512 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2513 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2514 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2515 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2516
2517 // flipped(empty) cull_rect vs unflipped diff_rect
2518 // == empty
2519 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2520 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2521 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2522 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2523 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2524 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2525
2526 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2527 // == empty
2528 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2529 << label;
2530 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), Rect())
2531 << label;
2532 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2533 << label;
2534 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), Rect())
2535 << label;
2536 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2537 << label;
2538 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), Rect())
2539 << label;
2540 };
2541
2542 auto non_reducing = [&cull_rect, &check_empty_flips, &check_nans](
2543 const Rect& diff_rect, const std::string& label) {
2544 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2545 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2546 check_empty_flips(diff_rect, label);
2547 check_nans(diff_rect, label);
2548 };
2549
2550 auto reducing = [&cull_rect, &check_empty_flips, &check_nans](
2551 const Rect& diff_rect, const Rect& result_rect,
2552 const std::string& label) {
2553 EXPECT_TRUE(!result_rect.IsEmpty());
2554 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2555 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2556 check_empty_flips(diff_rect, label);
2557 check_nans(diff_rect, label);
2558 };
2559
2560 auto emptying = [&cull_rect, &check_empty_flips, &check_nans](
2561 const Rect& diff_rect, const std::string& label) {
2562 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2563 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), Rect()) << label;
2564 check_empty_flips(diff_rect, label);
2565 check_nans(diff_rect, label);
2566 };
2567
2568 // Skim the corners and edge
2569 non_reducing(Rect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2570 non_reducing(Rect::MakeLTRB(20, 10, 40, 20), "Above");
2571 non_reducing(Rect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2572 non_reducing(Rect::MakeLTRB(40, 20, 50, 40), "Right");
2573 non_reducing(Rect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2574 non_reducing(Rect::MakeLTRB(20, 40, 40, 50), "Below");
2575 non_reducing(Rect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2576 non_reducing(Rect::MakeLTRB(10, 20, 20, 40), "Left");
2577
2578 // Overlap corners
2579 non_reducing(Rect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2580 non_reducing(Rect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2581 non_reducing(Rect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2582 non_reducing(Rect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2583
2584 // Overlap edges, but not across an entire side
2585 non_reducing(Rect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2586 non_reducing(Rect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2587 non_reducing(Rect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2588 non_reducing(Rect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2589 non_reducing(Rect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2590 non_reducing(Rect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2591 non_reducing(Rect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2592 non_reducing(Rect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2593
2594 // Slice all the way through the middle
2595 non_reducing(Rect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2596 non_reducing(Rect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2597
2598 // Slice off each edge
2599 reducing(Rect::MakeLTRB(20, 15, 40, 25), //
2600 Rect::MakeLTRB(20, 25, 40, 40), //
2601 "Slice off top");
2602 reducing(Rect::MakeLTRB(35, 20, 45, 40), //
2603 Rect::MakeLTRB(20, 20, 35, 40), //
2604 "Slice off right");
2605 reducing(Rect::MakeLTRB(20, 35, 40, 45), //
2606 Rect::MakeLTRB(20, 20, 40, 35), //
2607 "Slice off bottom");
2608 reducing(Rect::MakeLTRB(15, 20, 25, 40), //
2609 Rect::MakeLTRB(25, 20, 40, 40), //
2610 "Slice off left");
2611
2612 // cull rect contains diff rect
2613 non_reducing(Rect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2614
2615 // cull rect equals diff rect
2616 emptying(cull_rect, "Perfectly covering");
2617
2618 // diff rect contains cull rect
2619 emptying(Rect::MakeLTRB(15, 15, 45, 45), "Smothering");
2620}
IsFinite() const
Returns true if all of the fields of this floating point rectangle are finite.
Definition rect.h:255

◆ TEST() [304/399]

impeller::testing::TEST ( RectTest  ,
RectDefaultConstructor   
)

Definition at line 44 of file rect_unittests.cc.

44 {
45 Rect rect = Rect();
46
47 EXPECT_EQ(rect.GetLeft(), 0.0f);
48 EXPECT_EQ(rect.GetTop(), 0.0f);
49 EXPECT_EQ(rect.GetRight(), 0.0f);
50 EXPECT_EQ(rect.GetBottom(), 0.0f);
51 EXPECT_EQ(rect.GetX(), 0.0f);
52 EXPECT_EQ(rect.GetY(), 0.0f);
53 EXPECT_EQ(rect.GetWidth(), 0.0f);
54 EXPECT_EQ(rect.GetHeight(), 0.0f);
55 EXPECT_TRUE(rect.IsEmpty());
56 EXPECT_TRUE(rect.IsFinite());
57}

◆ TEST() [305/399]

impeller::testing::TEST ( RectTest  ,
RectDirections   
)

Definition at line 2812 of file rect_unittests.cc.

2812 {
2813 auto r = Rect::MakeLTRB(1, 2, 3, 4);
2814
2815 EXPECT_EQ(r.GetLeft(), 1);
2816 EXPECT_EQ(r.GetTop(), 2);
2817 EXPECT_EQ(r.GetRight(), 3);
2818 EXPECT_EQ(r.GetBottom(), 4);
2819
2820 EXPECT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
2821 EXPECT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
2822 EXPECT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
2823 EXPECT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
2824}

◆ TEST() [306/399]

impeller::testing::TEST ( RectTest  ,
RectDoesNotIntersectEmpty   
)

Definition at line 764 of file rect_unittests.cc.

764 {
765 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
766
767 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
768 const std::string& label) {
769 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(l, b, r, t)))
770 << label << " with Top/Bottom swapped";
771 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, b, l, t)))
772 << label << " with Left/Right swapped";
773 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, t, l, b)))
774 << label << " with all sides swapped";
775 };
776
777 test(20, 20, 30, 30, "Above and Left");
778 test(70, 20, 80, 30, "Above");
779 test(120, 20, 130, 30, "Above and Right");
780 test(120, 70, 130, 80, "Right");
781 test(120, 120, 130, 130, "Below and Right");
782 test(70, 120, 80, 130, "Below");
783 test(20, 120, 30, 130, "Below and Left");
784 test(20, 70, 30, 80, "Left");
785
786 test(70, 70, 80, 80, "Inside");
787
788 test(40, 70, 60, 80, "Straddling Left");
789 test(70, 40, 80, 60, "Straddling Top");
790 test(90, 70, 110, 80, "Straddling Right");
791 test(70, 90, 80, 110, "Straddling Bottom");
792}

◆ TEST() [307/399]

impeller::testing::TEST ( RectTest  ,
RectEmptyDeclaration   
)

Definition at line 14 of file rect_unittests.cc.

14 {
15 Rect rect;
16
17 EXPECT_EQ(rect.GetLeft(), 0.0f);
18 EXPECT_EQ(rect.GetTop(), 0.0f);
19 EXPECT_EQ(rect.GetRight(), 0.0f);
20 EXPECT_EQ(rect.GetBottom(), 0.0f);
21 EXPECT_EQ(rect.GetX(), 0.0f);
22 EXPECT_EQ(rect.GetY(), 0.0f);
23 EXPECT_EQ(rect.GetWidth(), 0.0f);
24 EXPECT_EQ(rect.GetHeight(), 0.0f);
25 EXPECT_TRUE(rect.IsEmpty());
26 EXPECT_TRUE(rect.IsFinite());
27}

◆ TEST() [308/399]

impeller::testing::TEST ( RectTest  ,
RectExpand   
)

Definition at line 1205 of file rect_unittests.cc.

1205 {
1206 auto rect = Rect::MakeLTRB(100, 100, 200, 200);
1207
1208 // Expand(T amount)
1209 EXPECT_EQ(rect.Expand(10), Rect::MakeLTRB(90, 90, 210, 210));
1210 EXPECT_EQ(rect.Expand(-10), Rect::MakeLTRB(110, 110, 190, 190));
1211
1212 // Expand(amount, amount)
1213 EXPECT_EQ(rect.Expand(10, 10), Rect::MakeLTRB(90, 90, 210, 210));
1214 EXPECT_EQ(rect.Expand(10, -10), Rect::MakeLTRB(90, 110, 210, 190));
1215 EXPECT_EQ(rect.Expand(-10, 10), Rect::MakeLTRB(110, 90, 190, 210));
1216 EXPECT_EQ(rect.Expand(-10, -10), Rect::MakeLTRB(110, 110, 190, 190));
1217
1218 // Expand(amount, amount, amount, amount)
1219 EXPECT_EQ(rect.Expand(10, 20, 30, 40), Rect::MakeLTRB(90, 80, 230, 240));
1220 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), Rect::MakeLTRB(110, 80, 230, 240));
1221 EXPECT_EQ(rect.Expand(10, -20, 30, 40), Rect::MakeLTRB(90, 120, 230, 240));
1222 EXPECT_EQ(rect.Expand(10, 20, -30, 40), Rect::MakeLTRB(90, 80, 170, 240));
1223 EXPECT_EQ(rect.Expand(10, 20, 30, -40), Rect::MakeLTRB(90, 80, 230, 160));
1224
1225 // Expand(Point amount)
1226 EXPECT_EQ(rect.Expand(Point{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1227 EXPECT_EQ(rect.Expand(Point{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1228 EXPECT_EQ(rect.Expand(Point{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1229 EXPECT_EQ(rect.Expand(Point{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1230
1231 // Expand(Size amount)
1232 EXPECT_EQ(rect.Expand(Size{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1233 EXPECT_EQ(rect.Expand(Size{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1234 EXPECT_EQ(rect.Expand(Size{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1235 EXPECT_EQ(rect.Expand(Size{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1236}

◆ TEST() [309/399]

impeller::testing::TEST ( RectTest  ,
RectFromRect   
)

Definition at line 609 of file rect_unittests.cc.

609 {
610 EXPECT_EQ(Rect(Rect::MakeXYWH(2, 3, 7, 15)),
611 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
612 EXPECT_EQ(Rect(Rect::MakeLTRB(2, 3, 7, 15)),
613 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
614}

◆ TEST() [310/399]

impeller::testing::TEST ( RectTest  ,
RectGetNormalizingTransform   
)

Definition at line 989 of file rect_unittests.cc.

989 {
990 {
991 // Checks for expected matrix values
992
993 auto r = Rect::MakeXYWH(100, 200, 200, 400);
994
995 EXPECT_EQ(r.GetNormalizingTransform(),
996 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
997 Matrix::MakeTranslation({-100, -200}));
998 }
999
1000 {
1001 // Checks for expected transform of points relative to the rect
1002
1003 auto r = Rect::MakeLTRB(300, 500, 400, 700);
1004 auto m = r.GetNormalizingTransform();
1005
1006 // The 4 corners of the rect => (0, 0) to (1, 1)
1007 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1008 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1009 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1010 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1011
1012 // The center => (0.5, 0.5)
1013 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1014
1015 // Outside the 4 corners => (-1, -1) to (2, 2)
1016 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1017 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1018 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1019 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1020 }
1021
1022 {
1023 // Checks for behavior with empty rects
1024
1025 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1026
1027 // Empty for width and/or height == 0
1028 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1029 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1030 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1031
1032 // Empty for width and/or height < 0
1033 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1034 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1035 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1036 }
1037
1038 {
1039 // Checks for behavior with non-finite rects
1040
1041 auto z = Matrix::MakeScale({0.0, 0.0, 1.0});
1042 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1043 auto inf = std::numeric_limits<Scalar>::infinity();
1044
1045 // Non-finite for width and/or height == nan
1046 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
1047 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
1048 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
1049
1050 // Non-finite for width and/or height == inf
1051 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
1052 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
1053 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
1054
1055 // Non-finite for width and/or height == -inf
1056 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
1057 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
1058 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
1059
1060 // Non-finite for origin X and/or Y == nan
1061 EXPECT_EQ(Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
1062 EXPECT_EQ(Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
1063 EXPECT_EQ(Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
1064
1065 // Non-finite for origin X and/or Y == inf
1066 EXPECT_EQ(Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
1067 EXPECT_EQ(Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
1068 EXPECT_EQ(Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
1069
1070 // Non-finite for origin X and/or Y == -inf
1071 EXPECT_EQ(Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
1072 EXPECT_EQ(Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
1073 EXPECT_EQ(Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
1074 }
1075}

◆ TEST() [311/399]

impeller::testing::TEST ( RectTest  ,
RectGetPoints   
)

Definition at line 2741 of file rect_unittests.cc.

2741 {
2742 {
2743 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2744 auto points = r.GetPoints();
2745 EXPECT_POINT_NEAR(points[0], Point(100, 200));
2746 EXPECT_POINT_NEAR(points[1], Point(400, 200));
2747 EXPECT_POINT_NEAR(points[2], Point(100, 600));
2748 EXPECT_POINT_NEAR(points[3], Point(400, 600));
2749 }
2750
2751 {
2752 Rect r = Rect::MakeMaximum();
2753 auto points = r.GetPoints();
2754 EXPECT_EQ(points[0], Point(std::numeric_limits<float>::lowest(),
2755 std::numeric_limits<float>::lowest()));
2756 EXPECT_EQ(points[1], Point(std::numeric_limits<float>::max(),
2757 std::numeric_limits<float>::lowest()));
2758 EXPECT_EQ(points[2], Point(std::numeric_limits<float>::lowest(),
2759 std::numeric_limits<float>::max()));
2760 EXPECT_EQ(points[3], Point(std::numeric_limits<float>::max(),
2761 std::numeric_limits<float>::max()));
2762 }
2763}
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle in a Z order that is compatible with tr...
Definition rect.h:382

◆ TEST() [312/399]

impeller::testing::TEST ( RectTest  ,
RectGetPositive   
)

Definition at line 2798 of file rect_unittests.cc.

2798 {
2799 {
2800 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2801 auto actual = r.GetPositive();
2802 EXPECT_RECT_NEAR(r, actual);
2803 }
2804 {
2805 Rect r = Rect::MakeXYWH(100, 200, -100, -100);
2806 auto actual = r.GetPositive();
2807 Rect expected = Rect::MakeXYWH(0, 100, 100, 100);
2808 EXPECT_RECT_NEAR(expected, actual);
2809 }
2810}
constexpr TRect GetPositive() const
Get a version of this rectangle that has a non-negative size.
Definition rect.h:366

◆ TEST() [313/399]

impeller::testing::TEST ( RectTest  ,
RectGetTransformedPoints   
)

Definition at line 2772 of file rect_unittests.cc.

2772 {
2773 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2774 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
2775 EXPECT_POINT_NEAR(points[0], Point(110, 220));
2776 EXPECT_POINT_NEAR(points[1], Point(410, 220));
2777 EXPECT_POINT_NEAR(points[2], Point(110, 620));
2778 EXPECT_POINT_NEAR(points[3], Point(410, 620));
2779}
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
Definition rect.h:394

◆ TEST() [314/399]

impeller::testing::TEST ( RectTest  ,
RectIntersection   
)

Definition at line 1580 of file rect_unittests.cc.

1580 {
1581 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1582 ASSERT_TRUE(a.IsFinite()) << label;
1583 ASSERT_TRUE(b.IsFinite()) << label;
1584
1585 for (int i = 1; i < 16; i++) {
1586 // NaN in a produces empty
1587 EXPECT_FALSE(swap_nan(a, i).Intersection(b).has_value())
1588 << label << ", index = " << i;
1589 // NaN in b produces empty
1590 EXPECT_FALSE(a.Intersection(swap_nan(b, i)).has_value())
1591 << label << ", index = " << i;
1592 // NaN in both is empty
1593 for (int j = 1; j < 16; j++) {
1594 EXPECT_FALSE(swap_nan(a, i).Intersection(swap_nan(b, j)).has_value())
1595 << label << ", indices = " << i << ", " << j;
1596 }
1597 }
1598 };
1599
1600 auto check_empty_flips = [](const Rect& a, const Rect& b,
1601 const std::string& label) {
1602 ASSERT_FALSE(a.IsEmpty());
1603 // b is allowed to be empty
1604
1605 // unflipped a vs flipped (empty) b yields a
1606 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1607 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1608 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1609
1610 // flipped (empty) a vs unflipped b yields b
1611 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1612 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1613 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1614
1615 // flipped (empty) a vs flipped (empty) b yields empty
1616 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1617 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1618 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1619 };
1620
1621 auto test_non_empty = [&check_nans, &check_empty_flips](
1622 const Rect& a, const Rect& b, const Rect& result) {
1623 ASSERT_FALSE(a.IsEmpty()) << a;
1624 // b is allowed to be empty
1625
1626 std::stringstream stream;
1627 stream << a << " union " << b;
1628 auto label = stream.str();
1629
1630 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1631 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1632 EXPECT_EQ(a.Intersection(b), result) << label;
1633 EXPECT_EQ(b.Intersection(a), result) << label;
1634 check_empty_flips(a, b, label);
1635 check_nans(a, b, label);
1636 };
1637
1638 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1639 const Rect& b) {
1640 ASSERT_FALSE(a.IsEmpty()) << a;
1641 // b is allowed to be empty
1642
1643 std::stringstream stream;
1644 stream << a << " union " << b;
1645 auto label = stream.str();
1646
1647 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1648 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1649 check_empty_flips(a, b, label);
1650 check_nans(a, b, label);
1651 };
1652
1653 {
1654 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1655 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1656
1657 test_empty(a, b);
1658 }
1659
1660 {
1661 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1662 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1663
1664 test_empty(a, b);
1665 }
1666
1667 {
1668 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1669 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1670 auto expected = Rect::MakeXYWH(10, 10, 90, 90);
1671
1672 test_non_empty(a, b, expected);
1673 }
1674
1675 {
1676 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1677 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1678
1679 test_empty(a, b);
1680 }
1681
1682 {
1683 auto a = Rect::MakeMaximum();
1684 auto b = Rect::MakeXYWH(10, 10, 300, 300);
1685
1686 test_non_empty(a, b, b);
1687 }
1688
1689 {
1690 auto a = Rect::MakeMaximum();
1691 auto b = Rect::MakeMaximum();
1692
1693 test_non_empty(a, b, Rect::MakeMaximum());
1694 }
1695}

◆ TEST() [315/399]

impeller::testing::TEST ( RectTest  ,
RectIntersectsWithRect   
)

Definition at line 1902 of file rect_unittests.cc.

1902 {
1903 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1904 ASSERT_TRUE(a.IsFinite()) << label;
1905 ASSERT_TRUE(b.IsFinite()) << label;
1906
1907 for (int i = 1; i < 16; i++) {
1908 // NaN in a produces b
1909 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(b))
1910 << label << ", index = " << i;
1911 // NaN in b produces a
1912 EXPECT_FALSE(a.IntersectsWithRect(swap_nan(b, i)))
1913 << label << ", index = " << i;
1914 // NaN in both is empty
1915 for (int j = 1; j < 16; j++) {
1916 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(swap_nan(b, j)))
1917 << label << ", indices = " << i << ", " << j;
1918 }
1919 }
1920 };
1921
1922 auto check_empty_flips = [](const Rect& a, const Rect& b,
1923 const std::string& label) {
1924 ASSERT_FALSE(a.IsEmpty());
1925 // b is allowed to be empty
1926
1927 // unflipped a vs flipped (empty) b yields a
1928 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
1929 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
1930 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
1931
1932 // flipped (empty) a vs unflipped b yields b
1933 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
1934 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
1935 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
1936
1937 // flipped (empty) a vs flipped (empty) b yields empty
1938 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
1939 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
1940 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
1941 };
1942
1943 auto test_non_empty = [&check_nans, &check_empty_flips](const Rect& a,
1944 const Rect& b) {
1945 ASSERT_FALSE(a.IsEmpty()) << a;
1946 // b is allowed to be empty
1947
1948 std::stringstream stream;
1949 stream << a << " union " << b;
1950 auto label = stream.str();
1951
1952 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
1953 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
1954 check_empty_flips(a, b, label);
1955 check_nans(a, b, label);
1956 };
1957
1958 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1959 const Rect& b) {
1960 ASSERT_FALSE(a.IsEmpty()) << a;
1961 // b is allowed to be empty
1962
1963 std::stringstream stream;
1964 stream << a << " union " << b;
1965 auto label = stream.str();
1966
1967 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
1968 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
1969 check_empty_flips(a, b, label);
1970 check_nans(a, b, label);
1971 };
1972
1973 {
1974 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1975 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1976
1977 test_empty(a, b);
1978 }
1979
1980 {
1981 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1982 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1983
1984 test_empty(a, b);
1985 }
1986
1987 {
1988 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1989 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1990
1991 test_non_empty(a, b);
1992 }
1993
1994 {
1995 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1996 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1997
1998 test_empty(a, b);
1999 }
2000
2001 {
2002 auto a = Rect::MakeMaximum();
2003 auto b = Rect::MakeXYWH(10, 10, 100, 100);
2004
2005 test_non_empty(a, b);
2006 }
2007
2008 {
2009 auto a = Rect::MakeMaximum();
2010 auto b = Rect::MakeMaximum();
2011
2012 test_non_empty(a, b);
2013 }
2014}

◆ TEST() [316/399]

impeller::testing::TEST ( RectTest  ,
RectMakeMaximum   
)

Definition at line 575 of file rect_unittests.cc.

575 {
576 Rect rect = Rect::MakeMaximum();
577 auto inf = std::numeric_limits<Scalar>::infinity();
578 auto min = std::numeric_limits<Scalar>::lowest();
579 auto max = std::numeric_limits<Scalar>::max();
580
581 EXPECT_EQ(rect.GetLeft(), min);
582 EXPECT_EQ(rect.GetTop(), min);
583 EXPECT_EQ(rect.GetRight(), max);
584 EXPECT_EQ(rect.GetBottom(), max);
585 EXPECT_EQ(rect.GetX(), min);
586 EXPECT_EQ(rect.GetY(), min);
587 EXPECT_EQ(rect.GetWidth(), inf);
588 EXPECT_EQ(rect.GetHeight(), inf);
589 EXPECT_FALSE(rect.IsEmpty());
590 EXPECT_TRUE(rect.IsFinite());
591}

◆ TEST() [317/399]

impeller::testing::TEST ( RectTest  ,
RectMakePointBounds   
)

Definition at line 2781 of file rect_unittests.cc.

2781 {
2782 {
2783 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
2784 auto r = Rect::MakePointBounds(points.begin(), points.end());
2785 auto expected = Rect::MakeXYWH(0, -1, 4, 7);
2786 EXPECT_TRUE(r.has_value());
2787 if (r.has_value()) {
2788 EXPECT_RECT_NEAR(r.value(), expected);
2789 }
2790 }
2791 {
2792 std::vector<Point> points;
2793 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
2794 EXPECT_FALSE(r.has_value());
2795 }
2796}

◆ TEST() [318/399]

impeller::testing::TEST ( RectTest  ,
RectMakeSize   
)

Definition at line 545 of file rect_unittests.cc.

545 {
546 {
547 Size s(100, 200);
548 Rect r = Rect::MakeSize(s);
549 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
550 EXPECT_RECT_NEAR(r, expected);
551 }
552
553 {
554 ISize s(100, 200);
555 Rect r = Rect::MakeSize(s);
556 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
557 EXPECT_RECT_NEAR(r, expected);
558 }
559
560 {
561 Size s(100, 200);
562 IRect r = IRect::MakeSize(s);
563 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
564 EXPECT_EQ(r, expected);
565 }
566
567 {
568 ISize s(100, 200);
569 IRect r = IRect::MakeSize(s);
570 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
571 EXPECT_EQ(r, expected);
572 }
573}

◆ TEST() [319/399]

impeller::testing::TEST ( RectTest  ,
RectOriginSizeXYWHGetters   
)

Definition at line 657 of file rect_unittests.cc.

657 {
658 {
659 Rect r = Rect::MakeOriginSize({10, 20}, {50, 40});
660 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
661 EXPECT_EQ(r.GetSize(), Size(50, 40));
662 EXPECT_EQ(r.GetX(), 10);
663 EXPECT_EQ(r.GetY(), 20);
664 EXPECT_EQ(r.GetWidth(), 50);
665 EXPECT_EQ(r.GetHeight(), 40);
666 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
667 EXPECT_EQ(r.GetXYWH(), expected_array);
668 }
669
670 {
671 Rect r = Rect::MakeLTRB(10, 20, 50, 40);
672 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
673 EXPECT_EQ(r.GetSize(), Size(40, 20));
674 EXPECT_EQ(r.GetX(), 10);
675 EXPECT_EQ(r.GetY(), 20);
676 EXPECT_EQ(r.GetWidth(), 40);
677 EXPECT_EQ(r.GetHeight(), 20);
678 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
679 EXPECT_EQ(r.GetXYWH(), expected_array);
680 }
681}

◆ TEST() [320/399]

impeller::testing::TEST ( RectTest  ,
RectOverflowLTRB   
)

Definition at line 339 of file rect_unittests.cc.

339 {
340 auto min = std::numeric_limits<Scalar>::lowest();
341 auto max = std::numeric_limits<Scalar>::max();
342 auto inf = std::numeric_limits<Scalar>::infinity();
343
344 // 8 cases:
345 // finite negative X, max W
346 // ~min X, ~max W
347 // finite negative Y, max H
348 // ~min Y, ~max H
349 // finite positive X, min W
350 // ~min X, ~min W
351 // finite positive Y, min H
352 // ~min Y, ~min H
353
354 // a small finite value subtracted from a max value will remain max
355 // a very large finite value (like min) subtracted from max will go to inf
356
357 {
358 Rect rect = Rect::MakeLTRB(-5.0f, 10.0f, max, 25.0f);
359
360 EXPECT_EQ(rect.GetLeft(), -5.0f);
361 EXPECT_EQ(rect.GetTop(), 10.0f);
362 EXPECT_EQ(rect.GetRight(), max);
363 EXPECT_EQ(rect.GetBottom(), 25.0f);
364 EXPECT_EQ(rect.GetX(), -5.0f);
365 EXPECT_EQ(rect.GetY(), 10.0f);
366 EXPECT_EQ(rect.GetWidth(), max);
367 EXPECT_EQ(rect.GetHeight(), 15.0f);
368 EXPECT_FALSE(rect.IsEmpty());
369 EXPECT_TRUE(rect.IsFinite());
370 }
371
372 {
373 Rect rect = Rect::MakeLTRB(min + 5.0f, 10.0f, max - 5.0f, 25.0f);
374
375 EXPECT_EQ(rect.GetLeft(), min + 5.0f);
376 EXPECT_EQ(rect.GetTop(), 10.0f);
377 EXPECT_EQ(rect.GetRight(), max - 5.0f);
378 EXPECT_EQ(rect.GetBottom(), 25.0f);
379 EXPECT_EQ(rect.GetX(), min + 5.0f);
380 EXPECT_EQ(rect.GetY(), 10.0f);
381 EXPECT_EQ(rect.GetWidth(), inf);
382 EXPECT_EQ(rect.GetHeight(), 15.0f);
383 EXPECT_FALSE(rect.IsEmpty());
384 EXPECT_TRUE(rect.IsFinite());
385 }
386
387 {
388 Rect rect = Rect::MakeLTRB(5.0f, -10.0f, 20.0f, max);
389
390 EXPECT_EQ(rect.GetLeft(), 5.0f);
391 EXPECT_EQ(rect.GetTop(), -10.0f);
392 EXPECT_EQ(rect.GetRight(), 20.0f);
393 EXPECT_EQ(rect.GetBottom(), max);
394 EXPECT_EQ(rect.GetX(), 5.0f);
395 EXPECT_EQ(rect.GetY(), -10.0f);
396 EXPECT_EQ(rect.GetWidth(), 15.0f);
397 EXPECT_EQ(rect.GetHeight(), max);
398 EXPECT_FALSE(rect.IsEmpty());
399 EXPECT_TRUE(rect.IsFinite());
400 }
401
402 {
403 Rect rect = Rect::MakeLTRB(5.0f, min + 10.0f, 20.0f, max - 15.0f);
404
405 EXPECT_EQ(rect.GetLeft(), 5.0f);
406 EXPECT_EQ(rect.GetTop(), min + 10.0f);
407 EXPECT_EQ(rect.GetRight(), 20.0f);
408 EXPECT_EQ(rect.GetBottom(), max - 15.0f);
409 EXPECT_EQ(rect.GetX(), 5.0f);
410 EXPECT_EQ(rect.GetY(), min + 10.0f);
411 EXPECT_EQ(rect.GetWidth(), 15.0f);
412 EXPECT_EQ(rect.GetHeight(), inf);
413 EXPECT_FALSE(rect.IsEmpty());
414 EXPECT_TRUE(rect.IsFinite());
415 }
416
417 {
418 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, min, 25.0f);
419
420 EXPECT_EQ(rect.GetLeft(), 5.0f);
421 EXPECT_EQ(rect.GetTop(), 10.0f);
422 EXPECT_EQ(rect.GetRight(), min);
423 EXPECT_EQ(rect.GetBottom(), 25.0f);
424 EXPECT_EQ(rect.GetX(), 5.0f);
425 EXPECT_EQ(rect.GetY(), 10.0f);
426 EXPECT_EQ(rect.GetWidth(), min);
427 EXPECT_EQ(rect.GetHeight(), 15.0f);
428 EXPECT_TRUE(rect.IsEmpty());
429 EXPECT_TRUE(rect.IsFinite());
430 }
431
432 {
433 Rect rect = Rect::MakeLTRB(max - 5.0f, 10.0f, min + 10.0f, 25.0f);
434
435 EXPECT_EQ(rect.GetLeft(), max - 5.0f);
436 EXPECT_EQ(rect.GetTop(), 10.0f);
437 EXPECT_EQ(rect.GetRight(), min + 10.0f);
438 EXPECT_EQ(rect.GetBottom(), 25.0f);
439 EXPECT_EQ(rect.GetX(), max - 5.0f);
440 EXPECT_EQ(rect.GetY(), 10.0f);
441 EXPECT_EQ(rect.GetWidth(), -inf);
442 EXPECT_EQ(rect.GetHeight(), 15.0f);
443 EXPECT_TRUE(rect.IsEmpty());
444 EXPECT_TRUE(rect.IsFinite());
445 }
446
447 {
448 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, 20.0f, min);
449
450 EXPECT_EQ(rect.GetLeft(), 5.0f);
451 EXPECT_EQ(rect.GetTop(), 10.0f);
452 EXPECT_EQ(rect.GetRight(), 20.0f);
453 EXPECT_EQ(rect.GetBottom(), min);
454 EXPECT_EQ(rect.GetX(), 5.0f);
455 EXPECT_EQ(rect.GetY(), 10.0f);
456 EXPECT_EQ(rect.GetWidth(), 15.0f);
457 EXPECT_EQ(rect.GetHeight(), min);
458 EXPECT_TRUE(rect.IsEmpty());
459 EXPECT_TRUE(rect.IsFinite());
460 }
461
462 {
463 Rect rect = Rect::MakeLTRB(5.0f, max - 5.0f, 20.0f, min + 10.0f);
464
465 EXPECT_EQ(rect.GetLeft(), 5.0f);
466 EXPECT_EQ(rect.GetTop(), max - 5.0f);
467 EXPECT_EQ(rect.GetRight(), 20.0f);
468 EXPECT_EQ(rect.GetBottom(), min + 10.0f);
469 EXPECT_EQ(rect.GetX(), 5.0f);
470 EXPECT_EQ(rect.GetY(), max - 5.0f);
471 EXPECT_EQ(rect.GetWidth(), 15.0f);
472 EXPECT_EQ(rect.GetHeight(), -inf);
473 EXPECT_TRUE(rect.IsEmpty());
474 EXPECT_TRUE(rect.IsFinite());
475 }
476}

◆ TEST() [321/399]

impeller::testing::TEST ( RectTest  ,
RectOverflowXYWH   
)

Definition at line 133 of file rect_unittests.cc.

133 {
134 auto min = std::numeric_limits<Scalar>::lowest();
135 auto max = std::numeric_limits<Scalar>::max();
136 auto inf = std::numeric_limits<Scalar>::infinity();
137
138 // 8 cases:
139 // finite X, max W
140 // max X, max W
141 // finite Y, max H
142 // max Y, max H
143 // finite X, min W
144 // min X, min W
145 // finite Y, min H
146 // min Y, min H
147
148 // a small finite value added to a max value will remain max
149 // a very large finite value (like max) added to max will go to infinity
150
151 {
152 Rect rect = Rect::MakeXYWH(5.0, 10.0f, max, 15.0f);
153
154 EXPECT_EQ(rect.GetLeft(), 5.0f);
155 EXPECT_EQ(rect.GetTop(), 10.0f);
156 EXPECT_EQ(rect.GetRight(), max);
157 EXPECT_EQ(rect.GetBottom(), 25.0f);
158 EXPECT_EQ(rect.GetX(), 5.0f);
159 EXPECT_EQ(rect.GetY(), 10.0f);
160 EXPECT_EQ(rect.GetWidth(), max);
161 EXPECT_EQ(rect.GetHeight(), 15.0f);
162 EXPECT_FALSE(rect.IsEmpty());
163 EXPECT_TRUE(rect.IsFinite());
164 }
165
166 {
167 Rect rect = Rect::MakeXYWH(max, 10.0f, max, 15.0f);
168
169 EXPECT_EQ(rect.GetLeft(), max);
170 EXPECT_EQ(rect.GetTop(), 10.0f);
171 EXPECT_EQ(rect.GetRight(), inf);
172 EXPECT_EQ(rect.GetBottom(), 25.0f);
173 EXPECT_EQ(rect.GetX(), max);
174 EXPECT_EQ(rect.GetY(), 10.0f);
175 EXPECT_EQ(rect.GetWidth(), inf);
176 EXPECT_EQ(rect.GetHeight(), 15.0f);
177 EXPECT_FALSE(rect.IsEmpty());
178 EXPECT_FALSE(rect.IsFinite());
179 }
180
181 {
182 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, max);
183
184 EXPECT_EQ(rect.GetLeft(), 5.0f);
185 EXPECT_EQ(rect.GetTop(), 10.0f);
186 EXPECT_EQ(rect.GetRight(), 25.0f);
187 EXPECT_EQ(rect.GetBottom(), max);
188 EXPECT_EQ(rect.GetX(), 5.0f);
189 EXPECT_EQ(rect.GetY(), 10.0f);
190 EXPECT_EQ(rect.GetWidth(), 20.0f);
191 EXPECT_EQ(rect.GetHeight(), max);
192 EXPECT_FALSE(rect.IsEmpty());
193 EXPECT_TRUE(rect.IsFinite());
194 }
195
196 {
197 Rect rect = Rect::MakeXYWH(5.0f, max, 20.0f, max);
198
199 EXPECT_EQ(rect.GetLeft(), 5.0f);
200 EXPECT_EQ(rect.GetTop(), max);
201 EXPECT_EQ(rect.GetRight(), 25.0f);
202 EXPECT_EQ(rect.GetBottom(), inf);
203 EXPECT_EQ(rect.GetX(), 5.0f);
204 EXPECT_EQ(rect.GetY(), max);
205 EXPECT_EQ(rect.GetWidth(), 20.0f);
206 EXPECT_EQ(rect.GetHeight(), inf);
207 EXPECT_FALSE(rect.IsEmpty());
208 EXPECT_FALSE(rect.IsFinite());
209 }
210
211 {
212 Rect rect = Rect::MakeXYWH(5.0, 10.0f, min, 15.0f);
213
214 EXPECT_EQ(rect.GetLeft(), 5.0f);
215 EXPECT_EQ(rect.GetTop(), 10.0f);
216 EXPECT_EQ(rect.GetRight(), min);
217 EXPECT_EQ(rect.GetBottom(), 25.0f);
218 EXPECT_EQ(rect.GetX(), 5.0f);
219 EXPECT_EQ(rect.GetY(), 10.0f);
220 EXPECT_EQ(rect.GetWidth(), min);
221 EXPECT_EQ(rect.GetHeight(), 15.0f);
222 EXPECT_TRUE(rect.IsEmpty());
223 EXPECT_TRUE(rect.IsFinite());
224 }
225
226 {
227 Rect rect = Rect::MakeXYWH(min, 10.0f, min, 15.0f);
228
229 EXPECT_EQ(rect.GetLeft(), min);
230 EXPECT_EQ(rect.GetTop(), 10.0f);
231 EXPECT_EQ(rect.GetRight(), -inf);
232 EXPECT_EQ(rect.GetBottom(), 25.0f);
233 EXPECT_EQ(rect.GetX(), min);
234 EXPECT_EQ(rect.GetY(), 10.0f);
235 EXPECT_EQ(rect.GetWidth(), -inf);
236 EXPECT_EQ(rect.GetHeight(), 15.0f);
237 EXPECT_TRUE(rect.IsEmpty());
238 EXPECT_FALSE(rect.IsFinite());
239 }
240
241 {
242 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, min);
243
244 EXPECT_EQ(rect.GetLeft(), 5.0f);
245 EXPECT_EQ(rect.GetTop(), 10.0f);
246 EXPECT_EQ(rect.GetRight(), 25.0f);
247 EXPECT_EQ(rect.GetBottom(), min);
248 EXPECT_EQ(rect.GetX(), 5.0f);
249 EXPECT_EQ(rect.GetY(), 10.0f);
250 EXPECT_EQ(rect.GetWidth(), 20.0f);
251 EXPECT_EQ(rect.GetHeight(), min);
252 EXPECT_TRUE(rect.IsEmpty());
253 EXPECT_TRUE(rect.IsFinite());
254 }
255
256 {
257 Rect rect = Rect::MakeXYWH(5.0f, min, 20.0f, min);
258
259 EXPECT_EQ(rect.GetLeft(), 5.0f);
260 EXPECT_EQ(rect.GetTop(), min);
261 EXPECT_EQ(rect.GetRight(), 25.0f);
262 EXPECT_EQ(rect.GetBottom(), -inf);
263 EXPECT_EQ(rect.GetX(), 5.0f);
264 EXPECT_EQ(rect.GetY(), min);
265 EXPECT_EQ(rect.GetWidth(), 20.0f);
266 EXPECT_EQ(rect.GetHeight(), -inf);
267 EXPECT_TRUE(rect.IsEmpty());
268 EXPECT_FALSE(rect.IsFinite());
269 }
270}

◆ TEST() [322/399]

impeller::testing::TEST ( RectTest  ,
RectProject   
)

Definition at line 2826 of file rect_unittests.cc.

2826 {
2827 {
2828 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2829 auto actual = r.Project(r);
2830 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
2831 EXPECT_RECT_NEAR(expected, actual);
2832 }
2833 {
2834 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2835 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
2836 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
2837 EXPECT_RECT_NEAR(expected, actual);
2838 }
2839}

◆ TEST() [323/399]

impeller::testing::TEST ( RectTest  ,
RectRound   
)

Definition at line 2865 of file rect_unittests.cc.

2865 {
2866 {
2867 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
2868 EXPECT_EQ(Rect::Round(r), r);
2869 }
2870 {
2871 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
2872 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-100, -200, 300, 400));
2873 }
2874 {
2875 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
2876 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-101, -201, 301, 401));
2877 }
2878}

◆ TEST() [324/399]

impeller::testing::TEST ( RectTest  ,
RectRoundOut   
)

Definition at line 2841 of file rect_unittests.cc.

2841 {
2842 {
2843 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
2844 EXPECT_EQ(Rect::RoundOut(r), r);
2845 }
2846 {
2847 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
2848 EXPECT_EQ(Rect::RoundOut(r), Rect::MakeLTRB(-101, -201, 301, 401));
2849 }
2850}

◆ TEST() [325/399]

impeller::testing::TEST ( RectTest  ,
RectRoundOutEmpty   
)

Definition at line 709 of file rect_unittests.cc.

709 {
710 Rect rect;
711
712 EXPECT_EQ(Rect::RoundOut(rect), Rect());
713
714 EXPECT_EQ(IRect::RoundOut(rect), IRect());
715}

◆ TEST() [326/399]

impeller::testing::TEST ( RectTest  ,
RectRoundOutSimple   
)

Definition at line 717 of file rect_unittests.cc.

717 {
718 Rect rect = Rect::MakeLTRB(5.125f, 10.75f, 20.625f, 25.375f);
719
720 EXPECT_EQ(Rect::RoundOut(rect), Rect::MakeLTRB(5.0f, 10.0f, 21.0f, 26.0f));
721
722 EXPECT_EQ(IRect::RoundOut(rect), IRect::MakeLTRB(5, 10, 21, 26));
723}

◆ TEST() [327/399]

impeller::testing::TEST ( RectTest  ,
RectRoundOutToIRectHuge   
)

Definition at line 725 of file rect_unittests.cc.

725 {
726 auto test = [](int corners) {
727 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
728 Scalar l, t, r, b;
729 int64_t il, it, ir, ib;
730 l = il = 50;
731 t = it = 50;
732 r = ir = 80;
733 b = ib = 80;
734 if ((corners & (1 << 0)) != 0) {
735 l = -1E20;
736 il = std::numeric_limits<int64_t>::min();
737 }
738 if ((corners & (1 << 1)) != 0) {
739 t = -1E20;
740 it = std::numeric_limits<int64_t>::min();
741 }
742 if ((corners & (1 << 2)) != 0) {
743 r = +1E20;
744 ir = std::numeric_limits<int64_t>::max();
745 }
746 if ((corners & (1 << 3)) != 0) {
747 b = +1E20;
748 ib = std::numeric_limits<int64_t>::max();
749 }
750
751 Rect rect = Rect::MakeLTRB(l, t, r, b);
752 IRect irect = IRect::RoundOut(rect);
753 EXPECT_EQ(irect.GetLeft(), il) << corners;
754 EXPECT_EQ(irect.GetTop(), it) << corners;
755 EXPECT_EQ(irect.GetRight(), ir) << corners;
756 EXPECT_EQ(irect.GetBottom(), ib) << corners;
757 };
758
759 for (int corners = 0; corners <= 15; corners++) {
760 test(corners);
761 }
762}

◆ TEST() [328/399]

impeller::testing::TEST ( RectTest  ,
RectScale   
)

Definition at line 884 of file rect_unittests.cc.

884 {
885 auto test1 = [](Rect rect, Scalar scale) {
886 Rect expected = Rect::MakeXYWH(rect.GetX() * scale, //
887 rect.GetY() * scale, //
888 rect.GetWidth() * scale, //
889 rect.GetHeight() * scale);
890
891 EXPECT_RECT_NEAR(rect.Scale(scale), expected) //
892 << rect << " * " << scale;
893 EXPECT_RECT_NEAR(rect.Scale(scale, scale), expected) //
894 << rect << " * " << scale;
895 EXPECT_RECT_NEAR(rect.Scale(Point(scale, scale)), expected) //
896 << rect << " * " << scale;
897 EXPECT_RECT_NEAR(rect.Scale(Size(scale, scale)), expected) //
898 << rect << " * " << scale;
899 };
900
901 auto test2 = [&test1](Rect rect, Scalar scale_x, Scalar scale_y) {
902 Rect expected = Rect::MakeXYWH(rect.GetX() * scale_x, //
903 rect.GetY() * scale_y, //
904 rect.GetWidth() * scale_x, //
905 rect.GetHeight() * scale_y);
906
907 EXPECT_RECT_NEAR(rect.Scale(scale_x, scale_y), expected) //
908 << rect << " * " << scale_x << ", " << scale_y;
909 EXPECT_RECT_NEAR(rect.Scale(Point(scale_x, scale_y)), expected) //
910 << rect << " * " << scale_x << ", " << scale_y;
911 EXPECT_RECT_NEAR(rect.Scale(Size(scale_x, scale_y)), expected) //
912 << rect << " * " << scale_x << ", " << scale_y;
913
914 test1(rect, scale_x);
915 test1(rect, scale_y);
916 };
917
918 test2(Rect::MakeLTRB(10, 15, 100, 150), 1.0, 0.0);
919 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 1.0);
920 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 0.0);
921 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, 3.5);
922 test2(Rect::MakeLTRB(10, 15, 100, 150), 3.5, 2.5);
923 test2(Rect::MakeLTRB(10, 15, -100, 150), 2.5, 3.5);
924 test2(Rect::MakeLTRB(10, 15, 100, -150), 2.5, 3.5);
925 test2(Rect::MakeLTRB(10, 15, 100, 150), -2.5, 3.5);
926 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, -3.5);
927}

◆ TEST() [329/399]

impeller::testing::TEST ( RectTest  ,
RectShift   
)

Definition at line 2765 of file rect_unittests.cc.

2765 {
2766 auto r = Rect::MakeLTRB(0, 0, 100, 100);
2767
2768 EXPECT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
2769 EXPECT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
2770}

◆ TEST() [330/399]

impeller::testing::TEST ( RectTest  ,
RectSimpleLTRB   
)

Definition at line 73 of file rect_unittests.cc.

73 {
74 // Using fractional-power-of-2 friendly values for equality tests
75 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
76
77 EXPECT_EQ(rect.GetLeft(), 5.125f);
78 EXPECT_EQ(rect.GetTop(), 10.25f);
79 EXPECT_EQ(rect.GetRight(), 20.625f);
80 EXPECT_EQ(rect.GetBottom(), 25.375f);
81 EXPECT_EQ(rect.GetX(), 5.125f);
82 EXPECT_EQ(rect.GetY(), 10.25f);
83 EXPECT_EQ(rect.GetWidth(), 15.5f);
84 EXPECT_EQ(rect.GetHeight(), 15.125f);
85 EXPECT_FALSE(rect.IsEmpty());
86 EXPECT_TRUE(rect.IsFinite());
87}

◆ TEST() [331/399]

impeller::testing::TEST ( RectTest  ,
RectSimpleXYWH   
)

Definition at line 103 of file rect_unittests.cc.

103 {
104 // Using fractional-power-of-2 friendly values for equality tests
105 Rect rect = Rect::MakeXYWH(5.125f, 10.25f, 15.5f, 15.125f);
106
107 EXPECT_EQ(rect.GetLeft(), 5.125f);
108 EXPECT_EQ(rect.GetTop(), 10.25f);
109 EXPECT_EQ(rect.GetRight(), 20.625f);
110 EXPECT_EQ(rect.GetBottom(), 25.375f);
111 EXPECT_EQ(rect.GetX(), 5.125f);
112 EXPECT_EQ(rect.GetY(), 10.25f);
113 EXPECT_EQ(rect.GetWidth(), 15.5f);
114 EXPECT_EQ(rect.GetHeight(), 15.125f);
115 EXPECT_FALSE(rect.IsEmpty());
116 EXPECT_TRUE(rect.IsFinite());
117}

◆ TEST() [332/399]

impeller::testing::TEST ( RectTest  ,
RectUnion   
)

Definition at line 1313 of file rect_unittests.cc.

1313 {
1314 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1315 ASSERT_TRUE(a.IsFinite()) << label;
1316 ASSERT_TRUE(b.IsFinite()) << label;
1317 ASSERT_FALSE(a.Union(b).IsEmpty());
1318
1319 for (int i = 1; i < 16; i++) {
1320 // NaN in a produces b
1321 EXPECT_EQ(swap_nan(a, i).Union(b), b) << label << ", index = " << i;
1322 // NaN in b produces a
1323 EXPECT_EQ(a.Union(swap_nan(b, i)), a) << label << ", index = " << i;
1324 // NaN in both is empty
1325 for (int j = 1; j < 16; j++) {
1326 EXPECT_TRUE(swap_nan(a, i).Union(swap_nan(b, j)).IsEmpty())
1327 << label << ", indices = " << i << ", " << j;
1328 }
1329 }
1330 };
1331
1332 auto check_empty_flips = [](const Rect& a, const Rect& b,
1333 const std::string& label) {
1334 ASSERT_FALSE(a.IsEmpty());
1335 // b is allowed to be empty
1336
1337 // unflipped a vs flipped (empty) b yields a
1338 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1339 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1340 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1341
1342 // flipped (empty) a vs unflipped b yields b
1343 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1344 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1345 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1346
1347 // flipped (empty) a vs flipped (empty) b yields empty
1348 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1349 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1350 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1351 };
1352
1353 auto test = [&check_nans, &check_empty_flips](const Rect& a, const Rect& b,
1354 const Rect& result) {
1355 ASSERT_FALSE(a.IsEmpty()) << a;
1356 // b is allowed to be empty
1357
1358 std::stringstream stream;
1359 stream << a << " union " << b;
1360 auto label = stream.str();
1361
1362 EXPECT_EQ(a.Union(b), result) << label;
1363 EXPECT_EQ(b.Union(a), result) << label;
1364 check_empty_flips(a, b, label);
1365 check_nans(a, b, label);
1366 };
1367
1368 {
1369 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1370 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1371 auto expected = Rect::MakeXYWH(100, 100, 100, 100);
1372 test(a, b, expected);
1373 }
1374
1375 {
1376 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1377 auto b = Rect::MakeXYWH(0, 0, 1, 1);
1378 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1379 test(a, b, expected);
1380 }
1381
1382 {
1383 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1384 auto b = Rect::MakeXYWH(10, 10, 1, 1);
1385 auto expected = Rect::MakeXYWH(10, 10, 190, 190);
1386 test(a, b, expected);
1387 }
1388
1389 {
1390 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1391 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1392 auto expected = Rect::MakeXYWH(0, 0, 110, 110);
1393 test(a, b, expected);
1394 }
1395
1396 {
1397 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1398 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1399 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1400 test(a, b, expected);
1401 }
1402}

◆ TEST() [333/399]

impeller::testing::TEST ( RectTest  ,
RectXYWHIsEmpty   
)

Definition at line 1127 of file rect_unittests.cc.

1127 {
1128 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1129
1130 // Non-empty
1131 EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
1132
1133 // Empty both width and height both 0 or negative, in all combinations
1134 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
1135 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
1136 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
1137 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
1138
1139 // Empty for 0 or negative width or height (but not both at the same time)
1140 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
1141 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
1142 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
1143 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
1144
1145 // Empty for NaN in width or height or both
1146 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
1147 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
1148 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
1149}

◆ TEST() [334/399]

impeller::testing::TEST ( RectTest  ,
TransformAndClipBounds   
)

Definition at line 2898 of file rect_unittests.cc.

2898 {
2899 {
2900 // This matrix should clip no corners.
2901 auto matrix = impeller::Matrix::MakeColumn(
2902 // clang-format off
2903 2.0f, 0.0f, 0.0f, 0.0f,
2904 0.0f, 4.0f, 0.0f, 0.0f,
2905 0.0f, 0.0f, 1.0f, 0.0f,
2906 0.0f, 0.0f, 0.0f, 8.0f
2907 // clang-format on
2908 );
2909 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
2910 // None of these should have a W<0
2911 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftTop()),
2912 Vector3(200.0f, 400.0f, 8.0f));
2913 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightTop()),
2914 Vector3(400.0f, 400.0f, 8.0f));
2915 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftBottom()),
2916 Vector3(200.0f, 800.0f, 8.0f));
2917 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightBottom()),
2918 Vector3(400.0f, 800.0f, 8.0f));
2919
2920 Rect expect = Rect::MakeLTRB(25.0f, 50.0f, 50.0f, 100.0f);
2921 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
2922 EXPECT_EQ(src.TransformAndClipBounds(matrix), expect);
2923 }
2924
2925 {
2926 // This matrix should clip one corner.
2927 auto matrix = impeller::Matrix::MakeColumn(
2928 // clang-format off
2929 2.0f, 0.0f, 0.0f, -0.01f,
2930 0.0f, 2.0f, 0.0f, -0.006f,
2931 0.0f, 0.0f, 1.0f, 0.0f,
2932 0.0f, 0.0f, 0.0f, 3.0f
2933 // clang-format on
2934 );
2935 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
2936 // Exactly one of these should have a W<0
2937 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
2938 Vector3(200.0f, 200.0f, 1.4f));
2939 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
2940 Vector3(400.0f, 200.0f, 0.4f));
2941 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
2942 Vector3(200.0f, 400.0f, 0.8f));
2943 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
2944 Vector3(400.0f, 400.0f, -0.2f));
2945
2946 Rect expect = Rect::MakeLTRB(142.85715f, 142.85715f, 6553600.f, 6553600.f);
2947 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
2948 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
2949 }
2950
2951 {
2952 // This matrix should clip two corners.
2953 auto matrix = impeller::Matrix::MakeColumn(
2954 // clang-format off
2955 2.0f, 0.0f, 0.0f, -.015f,
2956 0.0f, 2.0f, 0.0f, -.006f,
2957 0.0f, 0.0f, 1.0f, 0.0f,
2958 0.0f, 0.0f, 0.0f, 3.0f
2959 // clang-format on
2960 );
2961 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
2962 // Exactly two of these should have a W<0
2963 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
2964 Vector3(200.0f, 200.0f, 0.9f));
2965 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
2966 Vector3(400.0f, 200.0f, -0.6f));
2967 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
2968 Vector3(200.0f, 400.0f, 0.3f));
2969 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
2970 Vector3(400.0f, 400.0f, -1.2f));
2971
2972 Rect expect = Rect::MakeLTRB(222.2222f, 222.2222f, 5898373.f, 6553600.f);
2973 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
2974 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
2975 }
2976
2977 {
2978 // This matrix should clip three corners.
2980 // clang-format off
2981 2.0f, 0.0f, 0.0f, -.02f,
2982 0.0f, 2.0f, 0.0f, -.006f,
2983 0.0f, 0.0f, 1.0f, 0.0f,
2984 0.0f, 0.0f, 0.0f, 3.0f
2985 // clang-format on
2986 );
2987 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
2988 // Exactly three of these should have a W<0
2989 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
2990 Vector3(200.0f, 200.0f, 0.4f));
2991 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
2992 Vector3(400.0f, 200.0f, -1.6f));
2993 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
2994 Vector3(200.0f, 400.0f, -0.2f));
2995 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
2996 Vector3(400.0f, 400.0f, -2.2f));
2997
2998 Rect expect = Rect::MakeLTRB(499.99988f, 499.99988f, 5898340.f, 4369400.f);
2999 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3000 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3001 }
3002
3003 {
3004 // This matrix should clip all four corners.
3006 // clang-format off
3007 2.0f, 0.0f, 0.0f, -.025f,
3008 0.0f, 2.0f, 0.0f, -.006f,
3009 0.0f, 0.0f, 1.0f, 0.0f,
3010 0.0f, 0.0f, 0.0f, 3.0f
3011 // clang-format on
3012 );
3013 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3014 // All of these should have a W<0
3015 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3016 Vector3(200.0f, 200.0f, -0.1f));
3017 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3018 Vector3(400.0f, 200.0f, -2.6f));
3019 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3020 Vector3(200.0f, 400.0f, -0.7f));
3021 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3022 Vector3(400.0f, 400.0f, -3.2f));
3023
3024 EXPECT_TRUE(src.TransformAndClipBounds(matrix).IsEmpty());
3025 }
3026}
#define EXPECT_VECTOR3_NEAR(a, b)
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition matrix.h:69

◆ TEST() [335/399]

impeller::testing::TEST ( RenderPassBuilder  ,
CreatesMSAAResolveWithCorrectStore   
)

Definition at line 102 of file render_pass_builder_vk_unittests.cc.

102 {
104 auto const context = MockVulkanContextBuilder().Build();
105
106 // Create an MSAA color attachment.
107 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
108 SampleCount::kCount4, LoadAction::kClear,
109 StoreAction::kMultisampleResolve);
110
111 auto render_pass = builder.Build(context->GetDevice());
112
113 EXPECT_TRUE(!!render_pass);
114
115 auto maybe_color = builder.GetColorAttachments().find(0u);
116 ASSERT_NE(maybe_color, builder.GetColorAttachments().end());
117 auto color = maybe_color->second;
118
119 // MSAA Texture.
120 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eGeneral);
121 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
122 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
123 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eDontCare);
124
125 auto maybe_resolve = builder.GetResolves().find(0u);
126 ASSERT_NE(maybe_resolve, builder.GetResolves().end());
127 auto resolve = maybe_resolve->second;
128
129 // MSAA Resolve Texture.
130 EXPECT_EQ(resolve.initialLayout, vk::ImageLayout::eGeneral);
131 EXPECT_EQ(resolve.finalLayout, vk::ImageLayout::eGeneral);
132 EXPECT_EQ(resolve.loadOp, vk::AttachmentLoadOp::eClear);
133 EXPECT_EQ(resolve.storeOp, vk::AttachmentStoreOp::eStore);
134}

◆ TEST() [336/399]

impeller::testing::TEST ( RenderPassBuilder  ,
CreatesRenderPassWithCombinedDepthStencil   
)

Definition at line 30 of file render_pass_builder_vk_unittests.cc.

30 {
32 auto const context = MockVulkanContextBuilder().Build();
33
34 // Create a single color attachment with a transient depth stencil.
35 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
36 SampleCount::kCount1, LoadAction::kClear,
37 StoreAction::kStore);
38 builder.SetDepthStencilAttachment(PixelFormat::kD24UnormS8Uint,
39 SampleCount::kCount1, LoadAction::kDontCare,
40 StoreAction::kDontCare);
41
42 auto render_pass = builder.Build(context->GetDevice());
43
44 EXPECT_TRUE(!!render_pass);
45
46 auto maybe_color = builder.GetColorAttachments().find(0u);
47 ASSERT_NE(maybe_color, builder.GetColorAttachments().end());
48 auto color = maybe_color->second;
49
50 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eGeneral);
51 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
52 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
53 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eStore);
54
55 auto maybe_depth_stencil = builder.GetDepthStencil();
56 ASSERT_TRUE(maybe_depth_stencil.has_value());
57 if (!maybe_depth_stencil.has_value()) {
58 return;
59 }
60 auto depth_stencil = maybe_depth_stencil.value();
61
62 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
63 EXPECT_EQ(depth_stencil.finalLayout,
64 vk::ImageLayout::eDepthStencilAttachmentOptimal);
65 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
66 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
67 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
68 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
69}

◆ TEST() [337/399]

impeller::testing::TEST ( RenderPassBuilder  ,
CreatesRenderPassWithNoDepthStencil   
)

Definition at line 15 of file render_pass_builder_vk_unittests.cc.

15 {
17 auto const context = MockVulkanContextBuilder().Build();
18
19 // Create a single color attachment with a transient depth stencil.
20 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
21 SampleCount::kCount1, LoadAction::kClear,
22 StoreAction::kStore);
23
24 auto render_pass = builder.Build(context->GetDevice());
25
26 EXPECT_TRUE(!!render_pass);
27 EXPECT_FALSE(builder.GetDepthStencil().has_value());
28}

◆ TEST() [338/399]

impeller::testing::TEST ( RenderPassBuilder  ,
CreatesRenderPassWithOnlyStencil   
)

Definition at line 71 of file render_pass_builder_vk_unittests.cc.

71 {
73 auto const context = MockVulkanContextBuilder().Build();
74
75 // Create a single color attachment with a transient depth stencil.
76 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
77 SampleCount::kCount1, LoadAction::kClear,
78 StoreAction::kStore);
79 builder.SetStencilAttachment(PixelFormat::kS8UInt, SampleCount::kCount1,
80 LoadAction::kDontCare, StoreAction::kDontCare);
81
82 auto render_pass = builder.Build(context->GetDevice());
83
84 EXPECT_TRUE(!!render_pass);
85
86 auto maybe_depth_stencil = builder.GetDepthStencil();
87 ASSERT_TRUE(maybe_depth_stencil.has_value());
88 if (!maybe_depth_stencil.has_value()) {
89 return;
90 }
91 auto depth_stencil = maybe_depth_stencil.value();
92
93 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
94 EXPECT_EQ(depth_stencil.finalLayout,
95 vk::ImageLayout::eDepthStencilAttachmentOptimal);
96 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
97 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
98 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
99 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
100}

◆ TEST() [339/399]

impeller::testing::TEST ( ResourceManagerVKTest  ,
CreatesANewInstance   
)

Definition at line 18 of file resource_manager_vk_unittests.cc.

18 {
19 auto const a = ResourceManagerVK::Create();
20 auto const b = ResourceManagerVK::Create();
21 EXPECT_NE(a, b);
22}

◆ TEST() [340/399]

impeller::testing::TEST ( ResourceManagerVKTest  ,
IsThreadSafe   
)

Definition at line 58 of file resource_manager_vk_unittests.cc.

58 {
59 // In a typical app, there is a single ResourceManagerVK per app, shared b/w
60 // threads.
61 //
62 // This test ensures that the ResourceManagerVK is thread-safe.
63 std::weak_ptr<ResourceManagerVK> manager;
64
65 {
66 auto const manager = ResourceManagerVK::Create();
67
68 // Spawn two threads, and have them both put resources into the manager.
69 struct MockResource {};
70
71 std::thread thread1([&manager]() {
72 UniqueResourceVKT<MockResource>(manager, MockResource{});
73 });
74
75 std::thread thread2([&manager]() {
76 UniqueResourceVKT<MockResource>(manager, MockResource{});
77 });
78
79 thread1.join();
80 thread2.join();
81 }
82
83 // The thread should have terminated.
84 EXPECT_EQ(manager.lock(), nullptr);
85}
A unique handle to a resource which will be reclaimed by the specified resource manager.
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font manager
Definition switches.h:218

◆ TEST() [341/399]

impeller::testing::TEST ( ResourceManagerVKTest  ,
ReclaimMovesAResourceAndDestroysIt   
)

Definition at line 24 of file resource_manager_vk_unittests.cc.

24 {
25 auto const manager = ResourceManagerVK::Create();
26
27 auto waiter = fml::AutoResetWaitableEvent();
28 auto dead = false;
29 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
30
31 // Not killed immediately.
32 EXPECT_FALSE(waiter.IsSignaledForTest());
33
34 {
36 manager, std::move(rattle));
37 }
38
39 waiter.Wait();
40}

◆ TEST() [342/399]

impeller::testing::TEST ( ResourceManagerVKTest  ,
TerminatesWhenOutOfScope   
)

Definition at line 43 of file resource_manager_vk_unittests.cc.

43 {
44 // Originally, this shared_ptr was never destroyed, and the thread never
45 // terminated. This test ensures that the thread terminates when the
46 // ResourceManagerVK is out of scope.
47 std::weak_ptr<ResourceManagerVK> manager;
48
49 {
50 auto shared = ResourceManagerVK::Create();
51 manager = shared;
52 }
53
54 // The thread should have terminated.
55 EXPECT_EQ(manager.lock(), nullptr);
56}

◆ TEST() [343/399]

impeller::testing::TEST ( SaturatedMath  ,
CastingFiniteDoubleToFloatStaysFinite   
)

Definition at line 981 of file saturated_math_unittests.cc.

981 {
982 const double d_max = std::numeric_limits<double>::max();
983 const float f_max = std::numeric_limits<float>::max();
984
985 {
986 const float result = saturated::Cast<double, float>(d_max);
987 EXPECT_EQ(result, f_max);
988 }
989
990 {
991 const float result = saturated::Cast<double, float>(-d_max);
992 EXPECT_EQ(result, -f_max);
993 }
994}

◆ TEST() [344/399]

impeller::testing::TEST ( SaturatedMath  ,
CastingInfiniteDoubleToFloatStaysInfinite   
)

Definition at line 996 of file saturated_math_unittests.cc.

996 {
997 const double d_inf = std::numeric_limits<double>::infinity();
998 const float f_max = std::numeric_limits<float>::infinity();
999
1000 {
1001 const float result = saturated::Cast<double, float>(d_inf);
1002 EXPECT_EQ(result, f_max);
1003 }
1004
1005 {
1006 const float result = saturated::Cast<double, float>(-d_inf);
1007 EXPECT_EQ(result, -f_max);
1008 }
1009}

◆ TEST() [345/399]

impeller::testing::TEST ( SaturatedMath  ,
CastingInfiniteScalarToSignedIntProducesLimit   
)

Definition at line 1066 of file saturated_math_unittests.cc.

1066 {
1067 // larger than even any [u]int64_t;
1068 const Scalar inf = std::numeric_limits<Scalar>::infinity();
1069
1070 {
1071 const auto result = saturated::Cast<Scalar, int8_t>(inf);
1072 EXPECT_EQ(result, int8_t(0x7F));
1073 }
1074 {
1075 const auto result = saturated::Cast<Scalar, int8_t>(-inf);
1076 EXPECT_EQ(result, int8_t(0x80));
1077 }
1078
1079 {
1080 const auto result = saturated::Cast<Scalar, int16_t>(inf);
1081 EXPECT_EQ(result, int16_t(0x7FFF));
1082 }
1083 {
1084 const auto result = saturated::Cast<Scalar, int16_t>(-inf);
1085 EXPECT_EQ(result, int16_t(0x8000));
1086 }
1087
1088 {
1089 const auto result = saturated::Cast<Scalar, int32_t>(inf);
1090 EXPECT_EQ(result, int32_t(0x7FFFFFFF));
1091 }
1092 {
1093 const auto result = saturated::Cast<Scalar, int32_t>(-inf);
1094 EXPECT_EQ(result, int32_t(0x80000000));
1095 }
1096
1097 {
1098 const auto result = saturated::Cast<Scalar, int64_t>(inf);
1099 EXPECT_EQ(result, int64_t(0x7FFFFFFFFFFFFFFF));
1100 }
1101 {
1102 const auto result = saturated::Cast<Scalar, int64_t>(-inf);
1103 EXPECT_EQ(result, int64_t(0x8000000000000000));
1104 }
1105}

◆ TEST() [346/399]

impeller::testing::TEST ( SaturatedMath  ,
CastingLargeScalarToSignedIntProducesLimit   
)

Definition at line 1025 of file saturated_math_unittests.cc.

1025 {
1026 // larger than even any [u]int64_t;
1027 const Scalar large = 1e20f;
1028
1029 {
1030 const auto result = saturated::Cast<Scalar, int8_t>(large);
1031 EXPECT_EQ(result, int8_t(0x7F));
1032 }
1033 {
1034 const auto result = saturated::Cast<Scalar, int8_t>(-large);
1035 EXPECT_EQ(result, int8_t(0x80));
1036 }
1037
1038 {
1039 const auto result = saturated::Cast<Scalar, int16_t>(large);
1040 EXPECT_EQ(result, int16_t(0x7FFF));
1041 }
1042 {
1043 const auto result = saturated::Cast<Scalar, int16_t>(-large);
1044 EXPECT_EQ(result, int16_t(0x8000));
1045 }
1046
1047 {
1048 const auto result = saturated::Cast<Scalar, int32_t>(large);
1049 EXPECT_EQ(result, int32_t(0x7FFFFFFF));
1050 }
1051 {
1052 const auto result = saturated::Cast<Scalar, int32_t>(-large);
1053 EXPECT_EQ(result, int32_t(0x80000000));
1054 }
1055
1056 {
1057 const auto result = saturated::Cast<Scalar, int64_t>(large);
1058 EXPECT_EQ(result, int64_t(0x7FFFFFFFFFFFFFFF));
1059 }
1060 {
1061 const auto result = saturated::Cast<Scalar, int64_t>(-large);
1062 EXPECT_EQ(result, int64_t(0x8000000000000000));
1063 }
1064}

◆ TEST() [347/399]

impeller::testing::TEST ( SaturatedMath  ,
CastingNaNDoubleToFloatStaysNaN   
)

Definition at line 1011 of file saturated_math_unittests.cc.

1011 {
1012 const double d_nan = std::numeric_limits<double>::quiet_NaN();
1013
1014 {
1015 const float result = saturated::Cast<double, float>(d_nan);
1016 EXPECT_TRUE(std::isnan(result));
1017 }
1018
1019 {
1020 const float result = saturated::Cast<double, float>(-d_nan);
1021 EXPECT_TRUE(std::isnan(result));
1022 }
1023}

◆ TEST() [348/399]

impeller::testing::TEST ( SaturatedMath  ,
CastingNaNScalarToSignedIntProducesZero   
)

Definition at line 1107 of file saturated_math_unittests.cc.

1107 {
1108 // larger than even any [u]int64_t;
1109 const Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1110
1111 {
1112 const auto result = saturated::Cast<Scalar, int8_t>(nan);
1113 EXPECT_EQ(result, int8_t(0));
1114 }
1115
1116 {
1117 const auto result = saturated::Cast<Scalar, int16_t>(nan);
1118 EXPECT_EQ(result, int16_t(0));
1119 }
1120
1121 {
1122 const auto result = saturated::Cast<Scalar, int32_t>(nan);
1123 EXPECT_EQ(result, int32_t(0));
1124 }
1125
1126 {
1127 const auto result = saturated::Cast<Scalar, int64_t>(nan);
1128 EXPECT_EQ(result, int64_t(0));
1129 }
1130}

◆ TEST() [349/399]

impeller::testing::TEST ( SaturatedMath  ,
ExplicitAddOfFloatingPoint   
)

Definition at line 136 of file saturated_math_unittests.cc.

136 {
137 {
138 const float inf = std::numeric_limits<float>::infinity();
139 const float max = std::numeric_limits<float>::max();
140 const float big = max * 0.5f;
141
142 EXPECT_EQ(saturated::Add<float>(big, big), max);
143 EXPECT_EQ(saturated::Add<float>(max, big), inf);
144 EXPECT_EQ(saturated::Add<float>(big, max), inf);
145 EXPECT_EQ(saturated::Add<float>(max, max), inf);
146 EXPECT_EQ(saturated::Add<float>(max, inf), inf);
147 EXPECT_EQ(saturated::Add<float>(inf, max), inf);
148 EXPECT_EQ(saturated::Add<float>(inf, inf), inf);
149
150 EXPECT_EQ(saturated::Add<float>(-big, -big), -max);
151 EXPECT_EQ(saturated::Add<float>(-max, -big), -inf);
152 EXPECT_EQ(saturated::Add<float>(-big, -max), -inf);
153 EXPECT_EQ(saturated::Add<float>(-max, -max), -inf);
154 EXPECT_EQ(saturated::Add<float>(-max, -inf), -inf);
155 EXPECT_EQ(saturated::Add<float>(-inf, -max), -inf);
156 EXPECT_EQ(saturated::Add<float>(-inf, -inf), -inf);
157
158 EXPECT_EQ(saturated::Add<float>(big, -big), 0.0f);
159 EXPECT_EQ(saturated::Add<float>(max, -big), big);
160 EXPECT_EQ(saturated::Add<float>(big, -max), -big);
161 EXPECT_EQ(saturated::Add<float>(max, -max), 0.0f);
162 EXPECT_EQ(saturated::Add<float>(max, -inf), -inf);
163 EXPECT_EQ(saturated::Add<float>(inf, -max), inf);
164 EXPECT_TRUE(std::isnan(saturated::Add<float>(inf, -inf)));
165
166 EXPECT_EQ(saturated::Add<float>(-big, big), 0.0f);
167 EXPECT_EQ(saturated::Add<float>(-max, big), -big);
168 EXPECT_EQ(saturated::Add<float>(-big, max), big);
169 EXPECT_EQ(saturated::Add<float>(-max, max), 0.0f);
170 EXPECT_EQ(saturated::Add<float>(-max, inf), inf);
171 EXPECT_EQ(saturated::Add<float>(-inf, max), -inf);
172 EXPECT_TRUE(std::isnan(saturated::Add<float>(-inf, inf)));
173 }
174 {
175 const double inf = std::numeric_limits<double>::infinity();
176 const double max = std::numeric_limits<double>::max();
177 const double big = max * 0.5f;
178
179 EXPECT_EQ(saturated::Add<double>(big, big), max);
180 EXPECT_EQ(saturated::Add<double>(max, big), inf);
181 EXPECT_EQ(saturated::Add<double>(big, max), inf);
182 EXPECT_EQ(saturated::Add<double>(max, max), inf);
183 EXPECT_EQ(saturated::Add<double>(max, inf), inf);
184 EXPECT_EQ(saturated::Add<double>(inf, max), inf);
185 EXPECT_EQ(saturated::Add<double>(inf, inf), inf);
186
187 EXPECT_EQ(saturated::Add<double>(-big, -big), -max);
188 EXPECT_EQ(saturated::Add<double>(-max, -big), -inf);
189 EXPECT_EQ(saturated::Add<double>(-big, -max), -inf);
190 EXPECT_EQ(saturated::Add<double>(-max, -max), -inf);
191 EXPECT_EQ(saturated::Add<double>(-max, -inf), -inf);
192 EXPECT_EQ(saturated::Add<double>(-inf, -max), -inf);
193 EXPECT_EQ(saturated::Add<double>(-inf, -inf), -inf);
194
195 EXPECT_EQ(saturated::Add<double>(big, -big), 0.0f);
196 EXPECT_EQ(saturated::Add<double>(max, -big), big);
197 EXPECT_EQ(saturated::Add<double>(big, -max), -big);
198 EXPECT_EQ(saturated::Add<double>(max, -max), 0.0f);
199 EXPECT_EQ(saturated::Add<double>(max, -inf), -inf);
200 EXPECT_EQ(saturated::Add<double>(inf, -max), inf);
201 EXPECT_TRUE(std::isnan(saturated::Add<double>(inf, -inf)));
202
203 EXPECT_EQ(saturated::Add<double>(-big, big), 0.0f);
204 EXPECT_EQ(saturated::Add<double>(-max, big), -big);
205 EXPECT_EQ(saturated::Add<double>(-big, max), big);
206 EXPECT_EQ(saturated::Add<double>(-max, max), 0.0f);
207 EXPECT_EQ(saturated::Add<double>(-max, inf), inf);
208 EXPECT_EQ(saturated::Add<double>(-inf, max), -inf);
209 EXPECT_TRUE(std::isnan(saturated::Add<double>(-inf, inf)));
210 }
211 {
212 const Scalar inf = std::numeric_limits<Scalar>::infinity();
213 const Scalar max = std::numeric_limits<Scalar>::max();
214 const Scalar big = max * 0.5f;
215
216 EXPECT_EQ(saturated::Add<Scalar>(big, big), max);
217 EXPECT_EQ(saturated::Add<Scalar>(max, big), inf);
218 EXPECT_EQ(saturated::Add<Scalar>(big, max), inf);
219 EXPECT_EQ(saturated::Add<Scalar>(max, max), inf);
220 EXPECT_EQ(saturated::Add<Scalar>(max, inf), inf);
221 EXPECT_EQ(saturated::Add<Scalar>(inf, max), inf);
222 EXPECT_EQ(saturated::Add<Scalar>(inf, inf), inf);
223
224 EXPECT_EQ(saturated::Add<Scalar>(-big, -big), -max);
225 EXPECT_EQ(saturated::Add<Scalar>(-max, -big), -inf);
226 EXPECT_EQ(saturated::Add<Scalar>(-big, -max), -inf);
227 EXPECT_EQ(saturated::Add<Scalar>(-max, -max), -inf);
228 EXPECT_EQ(saturated::Add<Scalar>(-max, -inf), -inf);
229 EXPECT_EQ(saturated::Add<Scalar>(-inf, -max), -inf);
230 EXPECT_EQ(saturated::Add<Scalar>(-inf, -inf), -inf);
231
232 EXPECT_EQ(saturated::Add<Scalar>(big, -big), 0.0f);
233 EXPECT_EQ(saturated::Add<Scalar>(max, -big), big);
234 EXPECT_EQ(saturated::Add<Scalar>(big, -max), -big);
235 EXPECT_EQ(saturated::Add<Scalar>(max, -max), 0.0f);
236 EXPECT_EQ(saturated::Add<Scalar>(max, -inf), -inf);
237 EXPECT_EQ(saturated::Add<Scalar>(inf, -max), inf);
238 EXPECT_TRUE(std::isnan(saturated::Add<Scalar>(inf, -inf)));
239
240 EXPECT_EQ(saturated::Add<Scalar>(-big, big), 0.0f);
241 EXPECT_EQ(saturated::Add<Scalar>(-max, big), -big);
242 EXPECT_EQ(saturated::Add<Scalar>(-big, max), big);
243 EXPECT_EQ(saturated::Add<Scalar>(-max, max), 0.0f);
244 EXPECT_EQ(saturated::Add<Scalar>(-max, inf), inf);
245 EXPECT_EQ(saturated::Add<Scalar>(-inf, max), -inf);
246 EXPECT_TRUE(std::isnan(saturated::Add<Scalar>(-inf, inf)));
247 }
248}

◆ TEST() [350/399]

impeller::testing::TEST ( SaturatedMath  ,
ExplicitAddOfSignedInts   
)

Definition at line 12 of file saturated_math_unittests.cc.

12 {
13 {
14 EXPECT_EQ(saturated::Add<int8_t>(0x79, 5), int8_t(0x7E));
15 EXPECT_EQ(saturated::Add<int8_t>(0x7A, 5), int8_t(0x7F));
16 EXPECT_EQ(saturated::Add<int8_t>(0x7B, 5), int8_t(0x7F));
17 }
18 {
19 EXPECT_EQ(saturated::Add<int8_t>(0x86, -5), int8_t(0x81));
20 EXPECT_EQ(saturated::Add<int8_t>(0x85, -5), int8_t(0x80));
21 EXPECT_EQ(saturated::Add<int8_t>(0x84, -5), int8_t(0x80));
22 }
23 {
24 EXPECT_EQ(saturated::Add<int16_t>(0x7FF9, 5), int16_t(0x7FFE));
25 EXPECT_EQ(saturated::Add<int16_t>(0x7FFA, 5), int16_t(0x7FFF));
26 EXPECT_EQ(saturated::Add<int16_t>(0x7FFB, 5), int16_t(0x7FFF));
27 }
28 {
29 EXPECT_EQ(saturated::Add<int16_t>(0x8006, -5), int16_t(0x8001));
30 EXPECT_EQ(saturated::Add<int16_t>(0x8005, -5), int16_t(0x8000));
31 EXPECT_EQ(saturated::Add<int16_t>(0x8004, -5), int16_t(0x8000));
32 }
33 {
34 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFF9, 5), int32_t(0x7FFFFFFE));
35 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFFA, 5), int32_t(0x7FFFFFFF));
36 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFFB, 5), int32_t(0x7FFFFFFF));
37 }
38 {
39 EXPECT_EQ(saturated::Add<int32_t>(0x80000006, -5), int32_t(0x80000001));
40 EXPECT_EQ(saturated::Add<int32_t>(0x80000005, -5), int32_t(0x80000000));
41 EXPECT_EQ(saturated::Add<int32_t>(0x80000004, -5), int32_t(0x80000000));
42 }
43 {
44 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFF9, 5),
45 int64_t(0x7FFFFFFFFFFFFFFE));
46 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFFA, 5),
47 int64_t(0x7FFFFFFFFFFFFFFF));
48 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFFB, 5),
49 int64_t(0x7FFFFFFFFFFFFFFF));
50 }
51 {
52 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000006, -5),
53 int64_t(0x8000000000000001));
54 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000005, -5),
55 int64_t(0x8000000000000000));
56 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000004, -5),
57 int64_t(0x8000000000000000));
58 }
59}

◆ TEST() [351/399]

impeller::testing::TEST ( SaturatedMath  ,
ExplicitAverageScalarOfFloatingPoint   
)

Definition at line 828 of file saturated_math_unittests.cc.

828 {
829 const Scalar s_inf = std::numeric_limits<Scalar>::infinity();
830 const Scalar s_max = std::numeric_limits<Scalar>::max();
831 const Scalar s_big = s_max * 0.5f;
832
833 {
834 const float inf = std::numeric_limits<Scalar>::infinity();
835 const float max = std::numeric_limits<float>::max();
836 const float big = max * 0.5f;
837
838 EXPECT_EQ(saturated::AverageScalar<float>(big, big), s_big);
839 EXPECT_EQ(saturated::AverageScalar<float>(max, max), s_max);
840 EXPECT_EQ(saturated::AverageScalar<float>(big, -big), 0.0f);
841 EXPECT_EQ(saturated::AverageScalar<float>(max, -max), 0.0f);
842 EXPECT_EQ(saturated::AverageScalar<float>(-big, big), 0.0f);
843 EXPECT_EQ(saturated::AverageScalar<float>(-max, max), 0.0f);
844 EXPECT_EQ(saturated::AverageScalar<float>(-big, -big), -s_big);
845 EXPECT_EQ(saturated::AverageScalar<float>(-max, -max), -s_max);
846
847 EXPECT_EQ(saturated::AverageScalar<float>(inf, inf), s_inf);
848 EXPECT_EQ(saturated::AverageScalar<float>(-inf, -inf), -s_inf);
849 EXPECT_TRUE(std::isnan(saturated::AverageScalar<float>(-inf, inf)));
850 EXPECT_TRUE(std::isnan(saturated::AverageScalar<float>(inf, -inf)));
851 }
852 {
853 const double inf = std::numeric_limits<Scalar>::infinity();
854 const double max = std::numeric_limits<double>::max();
855 const double big = max * 0.5;
856
857 // Most of the averages below using the double constants will
858 // overflow the Scalar return value and result in infinity,
859 // so we also test with some Scalar constants (promoted to double)
860 // to verify that they don't overflow in the double template
861 EXPECT_EQ(saturated::AverageScalar<double>(s_big, s_big), s_big);
862 EXPECT_EQ(saturated::AverageScalar<double>(s_max, s_max), s_max);
863 EXPECT_EQ(saturated::AverageScalar<double>(-s_big, -s_big), -s_big);
864 EXPECT_EQ(saturated::AverageScalar<double>(-s_max, -s_max), -s_max);
865
866 // And now testing continues with the double constants which
867 // mostly overflow
868 EXPECT_EQ(saturated::AverageScalar<double>(big, big), s_inf);
869 EXPECT_EQ(saturated::AverageScalar<double>(max, max), s_inf);
870 EXPECT_EQ(saturated::AverageScalar<double>(big, -big), 0.0f);
871 EXPECT_EQ(saturated::AverageScalar<double>(max, -max), 0.0f);
872 EXPECT_EQ(saturated::AverageScalar<double>(-big, big), 0.0f);
873 EXPECT_EQ(saturated::AverageScalar<double>(-max, max), 0.0f);
874 EXPECT_EQ(saturated::AverageScalar<double>(-big, -big), -s_inf);
875 EXPECT_EQ(saturated::AverageScalar<double>(-max, -max), -s_inf);
876
877 EXPECT_EQ(saturated::AverageScalar<double>(inf, inf), s_inf);
878 EXPECT_EQ(saturated::AverageScalar<double>(-inf, -inf), -s_inf);
879 EXPECT_TRUE(std::isnan(saturated::AverageScalar<double>(-inf, inf)));
880 EXPECT_TRUE(std::isnan(saturated::AverageScalar<double>(inf, -inf)));
881 }
882 {
883 const Scalar inf = std::numeric_limits<Scalar>::infinity();
884 const Scalar max = std::numeric_limits<Scalar>::max();
885 const Scalar big = max * 0.5f;
886
887 EXPECT_EQ(saturated::AverageScalar<Scalar>(big, big), s_big);
888 EXPECT_EQ(saturated::AverageScalar<Scalar>(max, max), s_max);
889 EXPECT_EQ(saturated::AverageScalar<Scalar>(big, -big), 0.0f);
890 EXPECT_EQ(saturated::AverageScalar<Scalar>(max, -max), 0.0f);
891 EXPECT_EQ(saturated::AverageScalar<Scalar>(-big, big), 0.0f);
892 EXPECT_EQ(saturated::AverageScalar<Scalar>(-max, max), 0.0f);
893 EXPECT_EQ(saturated::AverageScalar<Scalar>(-big, -big), -s_big);
894 EXPECT_EQ(saturated::AverageScalar<Scalar>(-max, -max), -s_max);
895
896 EXPECT_EQ(saturated::AverageScalar<Scalar>(inf, inf), s_inf);
897 EXPECT_EQ(saturated::AverageScalar<Scalar>(-inf, -inf), -s_inf);
898 EXPECT_TRUE(std::isnan(saturated::AverageScalar<Scalar>(-inf, s_inf)));
899 EXPECT_TRUE(std::isnan(saturated::AverageScalar<Scalar>(inf, -s_inf)));
900 }
901}

◆ TEST() [352/399]

impeller::testing::TEST ( SaturatedMath  ,
ExplicitAverageScalarOfSignedInts   
)

Definition at line 716 of file saturated_math_unittests.cc.

716 {
717 // For each type try:
718 //
719 // - near the limits, averaging to 0
720 // - at the limits, averaging to 0 or 0.5 depending on precision
721 // - both large enough for the sum to overflow
722 // - both negative enough for the sum to underflow
723 {
724 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x81, 0x7F), -0.0f);
725 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x80, 0x7F), -0.5f);
726 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x70, 0x75), 114.5f);
727 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x85, 0x8A), -120.5f);
728 }
729 {
730 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8001, 0x7FFF), -0.0f);
731 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8000, 0x7FFF), -0.5f);
732 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x7000, 0x7005), 28674.5f);
733 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8005, 0x800A), -32760.5f);
734 }
735 {
736 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000001, 0x7FFFFFFF), -0.0f);
737 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000000, 0x7FFFFFFF), -0.5f);
738 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x70000000, 0x70000005),
739 1879048195.5f);
740 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000005, 0x8000000A),
741 -2147483655.5f);
742 }
743 {
744 EXPECT_EQ(saturated::AverageScalar<int64_t>(0x8000000000000001,
745 0x7FFFFFFFFFFFFFFF),
746 0.0f);
747 // 64-bit integers overflow the ability of a Scalar (float) to
748 // represent discrete integers and so the two numbers we are
749 // averaging here will look like the same number with different
750 // signs and the answer will be "0"
751 EXPECT_EQ(saturated::AverageScalar<int64_t>(0x8000000000000000,
752 0x7FFFFFFFFFFFFFFF),
753 0.0f);
754 EXPECT_NEAR(saturated::AverageScalar<int64_t>(0x7000000000000000,
755 0x7000000000000005),
756 8.07045053e+18, 1e18);
757 EXPECT_NEAR(saturated::AverageScalar<int64_t>(0x8000000000000005,
758 0x800000000000000A),
759 -9.223372e+18, 1e18);
760 }
761}

◆ TEST() [353/399]

impeller::testing::TEST ( SaturatedMath  ,
ExplicitSubOfFloatingPoint   
)

Definition at line 488 of file saturated_math_unittests.cc.

488 {
489 {
490 const float inf = std::numeric_limits<float>::infinity();
491 const float max = std::numeric_limits<float>::max();
492 const float big = max * 0.5f;
493
494 EXPECT_EQ(saturated::Sub<float>(big, big), 0.0f);
495 EXPECT_EQ(saturated::Sub<float>(max, big), big);
496 EXPECT_EQ(saturated::Sub<float>(big, max), -big);
497 EXPECT_EQ(saturated::Sub<float>(max, max), 0.0f);
498 EXPECT_EQ(saturated::Sub<float>(max, inf), -inf);
499 EXPECT_EQ(saturated::Sub<float>(inf, max), inf);
500 EXPECT_TRUE(std::isnan(saturated::Sub<float>(inf, inf)));
501
502 EXPECT_EQ(saturated::Sub<float>(-big, -big), 0.0f);
503 EXPECT_EQ(saturated::Sub<float>(-max, -big), -big);
504 EXPECT_EQ(saturated::Sub<float>(-big, -max), big);
505 EXPECT_EQ(saturated::Sub<float>(-max, -max), 0.0f);
506 EXPECT_EQ(saturated::Sub<float>(-max, -inf), inf);
507 EXPECT_EQ(saturated::Sub<float>(-inf, -max), -inf);
508 EXPECT_TRUE(std::isnan(saturated::Sub<float>(-inf, -inf)));
509
510 EXPECT_EQ(saturated::Sub<float>(big, -big), max);
511 EXPECT_EQ(saturated::Sub<float>(max, -big), inf);
512 EXPECT_EQ(saturated::Sub<float>(big, -max), inf);
513 EXPECT_EQ(saturated::Sub<float>(max, -max), inf);
514 EXPECT_EQ(saturated::Sub<float>(max, -inf), inf);
515 EXPECT_EQ(saturated::Sub<float>(inf, -max), inf);
516 EXPECT_EQ(saturated::Sub<float>(inf, -inf), inf);
517
518 EXPECT_EQ(saturated::Sub<float>(-big, big), -max);
519 EXPECT_EQ(saturated::Sub<float>(-max, big), -inf);
520 EXPECT_EQ(saturated::Sub<float>(-big, max), -inf);
521 EXPECT_EQ(saturated::Sub<float>(-max, max), -inf);
522 EXPECT_EQ(saturated::Sub<float>(-max, inf), -inf);
523 EXPECT_EQ(saturated::Sub<float>(-inf, max), -inf);
524 EXPECT_EQ(saturated::Sub<float>(-inf, inf), -inf);
525 }
526 {
527 const double inf = std::numeric_limits<double>::infinity();
528 const double max = std::numeric_limits<double>::max();
529 const double big = max * 0.5f;
530
531 EXPECT_EQ(saturated::Sub<double>(big, big), 0.0f);
532 EXPECT_EQ(saturated::Sub<double>(max, big), big);
533 EXPECT_EQ(saturated::Sub<double>(big, max), -big);
534 EXPECT_EQ(saturated::Sub<double>(max, max), 0.0f);
535 EXPECT_EQ(saturated::Sub<double>(max, inf), -inf);
536 EXPECT_EQ(saturated::Sub<double>(inf, max), inf);
537 EXPECT_TRUE(std::isnan(saturated::Sub<double>(inf, inf)));
538
539 EXPECT_EQ(saturated::Sub<double>(-big, -big), 0.0f);
540 EXPECT_EQ(saturated::Sub<double>(-max, -big), -big);
541 EXPECT_EQ(saturated::Sub<double>(-big, -max), big);
542 EXPECT_EQ(saturated::Sub<double>(-max, -max), 0.0f);
543 EXPECT_EQ(saturated::Sub<double>(-max, -inf), inf);
544 EXPECT_EQ(saturated::Sub<double>(-inf, -max), -inf);
545 EXPECT_TRUE(std::isnan(saturated::Sub<double>(-inf, -inf)));
546
547 EXPECT_EQ(saturated::Sub<double>(big, -big), max);
548 EXPECT_EQ(saturated::Sub<double>(max, -big), inf);
549 EXPECT_EQ(saturated::Sub<double>(big, -max), inf);
550 EXPECT_EQ(saturated::Sub<double>(max, -max), inf);
551 EXPECT_EQ(saturated::Sub<double>(max, -inf), inf);
552 EXPECT_EQ(saturated::Sub<double>(inf, -max), inf);
553 EXPECT_EQ(saturated::Sub<double>(inf, -inf), inf);
554
555 EXPECT_EQ(saturated::Sub<double>(-big, big), -max);
556 EXPECT_EQ(saturated::Sub<double>(-max, big), -inf);
557 EXPECT_EQ(saturated::Sub<double>(-big, max), -inf);
558 EXPECT_EQ(saturated::Sub<double>(-max, max), -inf);
559 EXPECT_EQ(saturated::Sub<double>(-max, inf), -inf);
560 EXPECT_EQ(saturated::Sub<double>(-inf, max), -inf);
561 EXPECT_EQ(saturated::Sub<double>(-inf, inf), -inf);
562 }
563 {
564 const Scalar inf = std::numeric_limits<Scalar>::infinity();
565 const Scalar max = std::numeric_limits<Scalar>::max();
566 const Scalar big = max * 0.5f;
567
568 EXPECT_EQ(saturated::Sub<Scalar>(big, big), 0.0f);
569 EXPECT_EQ(saturated::Sub<Scalar>(max, big), big);
570 EXPECT_EQ(saturated::Sub<Scalar>(big, max), -big);
571 EXPECT_EQ(saturated::Sub<Scalar>(max, max), 0.0f);
572 EXPECT_EQ(saturated::Sub<Scalar>(max, inf), -inf);
573 EXPECT_EQ(saturated::Sub<Scalar>(inf, max), inf);
574 EXPECT_TRUE(std::isnan(saturated::Sub<Scalar>(inf, inf)));
575
576 EXPECT_EQ(saturated::Sub<Scalar>(-big, -big), 0.0f);
577 EXPECT_EQ(saturated::Sub<Scalar>(-max, -big), -big);
578 EXPECT_EQ(saturated::Sub<Scalar>(-big, -max), big);
579 EXPECT_EQ(saturated::Sub<Scalar>(-max, -max), 0.0f);
580 EXPECT_EQ(saturated::Sub<Scalar>(-max, -inf), inf);
581 EXPECT_EQ(saturated::Sub<Scalar>(-inf, -max), -inf);
582 EXPECT_TRUE(std::isnan(saturated::Sub<Scalar>(-inf, -inf)));
583
584 EXPECT_EQ(saturated::Sub<Scalar>(big, -big), max);
585 EXPECT_EQ(saturated::Sub<Scalar>(max, -big), inf);
586 EXPECT_EQ(saturated::Sub<Scalar>(big, -max), inf);
587 EXPECT_EQ(saturated::Sub<Scalar>(max, -max), inf);
588 EXPECT_EQ(saturated::Sub<Scalar>(max, -inf), inf);
589 EXPECT_EQ(saturated::Sub<Scalar>(inf, -max), inf);
590 EXPECT_EQ(saturated::Sub<Scalar>(inf, -inf), inf);
591
592 EXPECT_EQ(saturated::Sub<Scalar>(-big, big), -max);
593 EXPECT_EQ(saturated::Sub<Scalar>(-max, big), -inf);
594 EXPECT_EQ(saturated::Sub<Scalar>(-big, max), -inf);
595 EXPECT_EQ(saturated::Sub<Scalar>(-max, max), -inf);
596 EXPECT_EQ(saturated::Sub<Scalar>(-max, inf), -inf);
597 EXPECT_EQ(saturated::Sub<Scalar>(-inf, max), -inf);
598 EXPECT_EQ(saturated::Sub<Scalar>(-inf, inf), -inf);
599 }
600}

◆ TEST() [354/399]

impeller::testing::TEST ( SaturatedMath  ,
ExplicitSubOfSignedInts   
)

Definition at line 364 of file saturated_math_unittests.cc.

364 {
365 {
366 EXPECT_EQ(saturated::Sub<int8_t>(0x79, -5), int8_t(0x7E));
367 EXPECT_EQ(saturated::Sub<int8_t>(0x7A, -5), int8_t(0x7F));
368 EXPECT_EQ(saturated::Sub<int8_t>(0x7B, -5), int8_t(0x7F));
369 }
370 {
371 EXPECT_EQ(saturated::Sub<int8_t>(0x86, 5), int8_t(0x81));
372 EXPECT_EQ(saturated::Sub<int8_t>(0x85, 5), int8_t(0x80));
373 EXPECT_EQ(saturated::Sub<int8_t>(0x84, 5), int8_t(0x80));
374 }
375 {
376 EXPECT_EQ(saturated::Sub<int16_t>(0x7FF9, -5), int16_t(0x7FFE));
377 EXPECT_EQ(saturated::Sub<int16_t>(0x7FFA, -5), int16_t(0x7FFF));
378 EXPECT_EQ(saturated::Sub<int16_t>(0x7FFB, -5), int16_t(0x7FFF));
379 }
380 {
381 EXPECT_EQ(saturated::Sub<int16_t>(0x8006, 5), int16_t(0x8001));
382 EXPECT_EQ(saturated::Sub<int16_t>(0x8005, 5), int16_t(0x8000));
383 EXPECT_EQ(saturated::Sub<int16_t>(0x8004, 5), int16_t(0x8000));
384 }
385 {
386 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFF9, -5), int32_t(0x7FFFFFFE));
387 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFFA, -5), int32_t(0x7FFFFFFF));
388 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFFB, -5), int32_t(0x7FFFFFFF));
389 }
390 {
391 EXPECT_EQ(saturated::Sub<int32_t>(0x80000006, 5), int32_t(0x80000001));
392 EXPECT_EQ(saturated::Sub<int32_t>(0x80000005, 5), int32_t(0x80000000));
393 EXPECT_EQ(saturated::Sub<int32_t>(0x80000004, 5), int32_t(0x80000000));
394 }
395 {
396 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFF9, -5),
397 int64_t(0x7FFFFFFFFFFFFFFE));
398 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFFA, -5),
399 int64_t(0x7FFFFFFFFFFFFFFF));
400 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFFB, -5),
401 int64_t(0x7FFFFFFFFFFFFFFF));
402 }
403 {
404 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000006, 5),
405 int64_t(0x8000000000000001));
406 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000005, 5),
407 int64_t(0x8000000000000000));
408 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000004, 5),
409 int64_t(0x8000000000000000));
410 }
411}

◆ TEST() [355/399]

impeller::testing::TEST ( SaturatedMath  ,
ImplicitAddOfFloatingPoint   
)

Definition at line 250 of file saturated_math_unittests.cc.

250 {
251 {
252 const float inf = std::numeric_limits<float>::infinity();
253 const float max = std::numeric_limits<float>::max();
254 const float big = max * 0.5f;
255
256 EXPECT_EQ(saturated::Add(big, big), max);
257 EXPECT_EQ(saturated::Add(max, big), inf);
258 EXPECT_EQ(saturated::Add(big, max), inf);
259 EXPECT_EQ(saturated::Add(max, max), inf);
260 EXPECT_EQ(saturated::Add(max, inf), inf);
261 EXPECT_EQ(saturated::Add(inf, max), inf);
262 EXPECT_EQ(saturated::Add(inf, inf), inf);
263
264 EXPECT_EQ(saturated::Add(-big, -big), -max);
265 EXPECT_EQ(saturated::Add(-max, -big), -inf);
266 EXPECT_EQ(saturated::Add(-big, -max), -inf);
267 EXPECT_EQ(saturated::Add(-max, -max), -inf);
268 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
269 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
270 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
271
272 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
273 EXPECT_EQ(saturated::Add(max, -big), big);
274 EXPECT_EQ(saturated::Add(big, -max), -big);
275 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
276 EXPECT_EQ(saturated::Add(max, -inf), -inf);
277 EXPECT_EQ(saturated::Add(inf, -max), inf);
278 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
279
280 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
281 EXPECT_EQ(saturated::Add(-max, big), -big);
282 EXPECT_EQ(saturated::Add(-big, max), big);
283 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
284 EXPECT_EQ(saturated::Add(-max, inf), inf);
285 EXPECT_EQ(saturated::Add(-inf, max), -inf);
286 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
287 }
288 {
289 const double inf = std::numeric_limits<double>::infinity();
290 const double max = std::numeric_limits<double>::max();
291 const double big = max * 0.5f;
292
293 EXPECT_EQ(saturated::Add(big, big), max);
294 EXPECT_EQ(saturated::Add(max, big), inf);
295 EXPECT_EQ(saturated::Add(big, max), inf);
296 EXPECT_EQ(saturated::Add(max, max), inf);
297 EXPECT_EQ(saturated::Add(max, inf), inf);
298 EXPECT_EQ(saturated::Add(inf, max), inf);
299 EXPECT_EQ(saturated::Add(inf, inf), inf);
300
301 EXPECT_EQ(saturated::Add(-big, -big), -max);
302 EXPECT_EQ(saturated::Add(-max, -big), -inf);
303 EXPECT_EQ(saturated::Add(-big, -max), -inf);
304 EXPECT_EQ(saturated::Add(-max, -max), -inf);
305 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
306 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
307 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
308
309 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
310 EXPECT_EQ(saturated::Add(max, -big), big);
311 EXPECT_EQ(saturated::Add(big, -max), -big);
312 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
313 EXPECT_EQ(saturated::Add(max, -inf), -inf);
314 EXPECT_EQ(saturated::Add(inf, -max), inf);
315 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
316
317 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
318 EXPECT_EQ(saturated::Add(-max, big), -big);
319 EXPECT_EQ(saturated::Add(-big, max), big);
320 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
321 EXPECT_EQ(saturated::Add(-max, inf), inf);
322 EXPECT_EQ(saturated::Add(-inf, max), -inf);
323 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
324 }
325 {
326 const Scalar inf = std::numeric_limits<Scalar>::infinity();
327 const Scalar max = std::numeric_limits<Scalar>::max();
328 const Scalar big = max * 0.5f;
329
330 EXPECT_EQ(saturated::Add(big, big), max);
331 EXPECT_EQ(saturated::Add(max, big), inf);
332 EXPECT_EQ(saturated::Add(big, max), inf);
333 EXPECT_EQ(saturated::Add(max, max), inf);
334 EXPECT_EQ(saturated::Add(max, inf), inf);
335 EXPECT_EQ(saturated::Add(inf, max), inf);
336 EXPECT_EQ(saturated::Add(inf, inf), inf);
337
338 EXPECT_EQ(saturated::Add(-big, -big), -max);
339 EXPECT_EQ(saturated::Add(-max, -big), -inf);
340 EXPECT_EQ(saturated::Add(-big, -max), -inf);
341 EXPECT_EQ(saturated::Add(-max, -max), -inf);
342 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
343 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
344 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
345
346 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
347 EXPECT_EQ(saturated::Add(max, -big), big);
348 EXPECT_EQ(saturated::Add(big, -max), -big);
349 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
350 EXPECT_EQ(saturated::Add(max, -inf), -inf);
351 EXPECT_EQ(saturated::Add(inf, -max), inf);
352 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
353
354 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
355 EXPECT_EQ(saturated::Add(-max, big), -big);
356 EXPECT_EQ(saturated::Add(-big, max), big);
357 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
358 EXPECT_EQ(saturated::Add(-max, inf), inf);
359 EXPECT_EQ(saturated::Add(-inf, max), -inf);
360 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
361 }
362}

◆ TEST() [356/399]

impeller::testing::TEST ( SaturatedMath  ,
ImplicitAddOfSignedInts   
)

Definition at line 61 of file saturated_math_unittests.cc.

61 {
62 {
63 int8_t a = 0x79;
64 int8_t b = 5;
65 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7E));
66 a = 0x7A;
67 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7F));
68 a = 0x7B;
69 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7F));
70 }
71 {
72 int8_t a = 0x86;
73 int8_t b = -5;
74 EXPECT_EQ(saturated::Add(a, b), int8_t(0x81));
75 a = 0x85;
76 EXPECT_EQ(saturated::Add(a, b), int8_t(0x80));
77 a = 0x84;
78 EXPECT_EQ(saturated::Add(a, b), int8_t(0x80));
79 }
80 {
81 int16_t a = 0x7FF9;
82 int16_t b = 5;
83 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFE));
84 a = 0x7FFA;
85 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFF));
86 a = 0x7FFB;
87 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFF));
88 }
89 {
90 int16_t a = 0x8006;
91 int16_t b = -5;
92 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8001));
93 a = 0x8005;
94 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8000));
95 a = 0x8004;
96 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8000));
97 }
98 {
99 int32_t a = 0x7FFFFFF9;
100 int32_t b = 5;
101 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFE));
102 a = 0x7FFFFFFA;
103 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFF));
104 a = 0x7FFFFFFB;
105 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFF));
106 }
107 {
108 int32_t a = 0x80000006;
109 int32_t b = -5;
110 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000001));
111 a = 0x80000005;
112 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000000));
113 a = 0x80000004;
114 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000000));
115 }
116 {
117 int64_t a = 0x7FFFFFFFFFFFFFF9;
118 int64_t b = 5;
119 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFE));
120 a = 0x7FFFFFFFFFFFFFFA;
121 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
122 a = 0x7FFFFFFFFFFFFFFB;
123 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
124 }
125 {
126 int64_t a = 0x8000000000000006;
127 int64_t b = -5;
128 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000001));
129 a = 0x8000000000000005;
130 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000000));
131 a = 0x8000000000000004;
132 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000000));
133 }
134}

◆ TEST() [357/399]

impeller::testing::TEST ( SaturatedMath  ,
ImplicitAverageScalarOfFloatingPoint   
)

Definition at line 903 of file saturated_math_unittests.cc.

903 {
904 // All return values are Scalar regardless of the operand types
905 // so these constants are used as the expected answers.
906 const Scalar s_inf = std::numeric_limits<Scalar>::infinity();
907 const Scalar s_max = std::numeric_limits<Scalar>::max();
908 const Scalar s_big = s_max * 0.5f;
909
910 {
911 const float inf = std::numeric_limits<float>::infinity();
912 const float max = std::numeric_limits<float>::max();
913 const float big = max * 0.5f;
914
915 EXPECT_EQ(saturated::AverageScalar(big, big), s_big);
916 EXPECT_EQ(saturated::AverageScalar(max, max), s_max);
917 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
918 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
919 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
920 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
921 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_big);
922 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_max);
923
924 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
925 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
926 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, inf)));
927 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -inf)));
928 }
929 {
930 const double inf = std::numeric_limits<double>::infinity();
931 const double max = std::numeric_limits<double>::max();
932 const double big = max * 0.5;
933
934 // The s_constants converted to double. We should get finite results
935 // from finding the averages of these values, but we'll get a lot of
936 // overflow to infinity when testing the large double constants.
937 const double d_s_max = s_max;
938 const double d_s_big = s_big;
939 EXPECT_EQ(saturated::AverageScalar(d_s_big, d_s_big), s_big);
940 EXPECT_EQ(saturated::AverageScalar(d_s_max, d_s_max), s_max);
941 EXPECT_EQ(saturated::AverageScalar(-d_s_big, -d_s_big), -s_big);
942 EXPECT_EQ(saturated::AverageScalar(-d_s_max, -d_s_max), -s_max);
943
944 // And now testing continues with the double constants which
945 // mostly overflow
946 EXPECT_EQ(saturated::AverageScalar(big, big), s_inf);
947 EXPECT_EQ(saturated::AverageScalar(max, max), s_inf);
948 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
949 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
950 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
951 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
952 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_inf);
953 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_inf);
954
955 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
956 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
957 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, inf)));
958 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -inf)));
959 }
960 {
961 const Scalar inf = std::numeric_limits<Scalar>::infinity();
962 const Scalar max = std::numeric_limits<Scalar>::max();
963 const Scalar big = max * 0.5f;
964
965 EXPECT_EQ(saturated::AverageScalar(big, big), s_big);
966 EXPECT_EQ(saturated::AverageScalar(max, max), s_max);
967 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
968 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
969 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
970 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
971 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_big);
972 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_max);
973
974 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
975 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
976 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, s_inf)));
977 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -s_inf)));
978 }
979}

◆ TEST() [358/399]

impeller::testing::TEST ( SaturatedMath  ,
ImplicitAverageScalarOfSignedInts   
)

Definition at line 763 of file saturated_math_unittests.cc.

763 {
764 // For each type try:
765 //
766 // - near the limits, averaging to 0
767 // - at the limits, averaging to 0 or 0.5 depending on precision
768 // - both large enough for the sum to overflow
769 // - both negative enough for the sum to underflow
770 {
771 int8_t a = 0x81;
772 int8_t b = 0x7f;
773 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
774 a = 0x80;
775 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
776 a = 0x70;
777 b = 0x75;
778 EXPECT_EQ(saturated::AverageScalar(a, b), 114.5f);
779 a = 0x85;
780 b = 0x8A;
781 EXPECT_EQ(saturated::AverageScalar(a, b), -120.5f);
782 }
783 {
784 int16_t a = 0x8001;
785 int16_t b = 0x7FFF;
786 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
787 a = 0x8000;
788 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
789 a = 0x7000;
790 b = 0x7005;
791 EXPECT_EQ(saturated::AverageScalar(a, b), 28674.5f);
792 a = 0x8005;
793 b = 0x800A;
794 EXPECT_EQ(saturated::AverageScalar(a, b), -32760.5f);
795 }
796 {
797 int32_t a = 0x80000001;
798 int32_t b = 0x7FFFFFFF;
799 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
800 a = 0x80000000;
801 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
802 a = 0x70000000;
803 b = 0x70000005;
804 EXPECT_EQ(saturated::AverageScalar(a, b), 1879048195.5f);
805 a = 0x80000005;
806 b = 0x8000000A;
807 EXPECT_EQ(saturated::AverageScalar(a, b), -2147483655.5f);
808 }
809 {
810 int64_t a = 0x8000000000000001;
811 int64_t b = 0x7FFFFFFFFFFFFFFF;
812 EXPECT_EQ(saturated::AverageScalar(a, b), 0.0f);
813 // 64-bit integers overflow the ability of a Scalar (float) to
814 // represent discrete integers and so the two numbers we are
815 // averaging here will look like the same number with different
816 // signs and the answer will be "0"
817 a = 0x8000000000000000;
818 EXPECT_EQ(saturated::AverageScalar<int64_t>(a, b), 0.0f);
819 a = 0x7000000000000000;
820 b = 0x7000000000000005;
821 EXPECT_NEAR(saturated::AverageScalar<int64_t>(a, b), 8.0704505e+18, 1e18);
822 a = 0x8000000000000005;
823 b = 0x800000000000000A;
824 EXPECT_NEAR(saturated::AverageScalar<int64_t>(a, b), -9.223372e+18, 1e18);
825 }
826}

◆ TEST() [359/399]

impeller::testing::TEST ( SaturatedMath  ,
ImplicitSubOfFloatingPoint   
)

Definition at line 602 of file saturated_math_unittests.cc.

602 {
603 {
604 const float inf = std::numeric_limits<float>::infinity();
605 const float max = std::numeric_limits<float>::max();
606 const float big = max * 0.5f;
607
608 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
609 EXPECT_EQ(saturated::Sub(max, big), big);
610 EXPECT_EQ(saturated::Sub(big, max), -big);
611 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
612 EXPECT_EQ(saturated::Sub(max, inf), -inf);
613 EXPECT_EQ(saturated::Sub(inf, max), inf);
614 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
615
616 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
617 EXPECT_EQ(saturated::Sub(-max, -big), -big);
618 EXPECT_EQ(saturated::Sub(-big, -max), big);
619 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
620 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
621 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
622 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
623
624 EXPECT_EQ(saturated::Sub(big, -big), max);
625 EXPECT_EQ(saturated::Sub(max, -big), inf);
626 EXPECT_EQ(saturated::Sub(big, -max), inf);
627 EXPECT_EQ(saturated::Sub(max, -max), inf);
628 EXPECT_EQ(saturated::Sub(max, -inf), inf);
629 EXPECT_EQ(saturated::Sub(inf, -max), inf);
630 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
631
632 EXPECT_EQ(saturated::Sub(-big, big), -max);
633 EXPECT_EQ(saturated::Sub(-max, big), -inf);
634 EXPECT_EQ(saturated::Sub(-big, max), -inf);
635 EXPECT_EQ(saturated::Sub(-max, max), -inf);
636 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
637 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
638 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
639 }
640 {
641 const double inf = std::numeric_limits<double>::infinity();
642 const double max = std::numeric_limits<double>::max();
643 const double big = max * 0.5f;
644
645 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
646 EXPECT_EQ(saturated::Sub(max, big), big);
647 EXPECT_EQ(saturated::Sub(big, max), -big);
648 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
649 EXPECT_EQ(saturated::Sub(max, inf), -inf);
650 EXPECT_EQ(saturated::Sub(inf, max), inf);
651 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
652
653 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
654 EXPECT_EQ(saturated::Sub(-max, -big), -big);
655 EXPECT_EQ(saturated::Sub(-big, -max), big);
656 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
657 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
658 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
659 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
660
661 EXPECT_EQ(saturated::Sub(big, -big), max);
662 EXPECT_EQ(saturated::Sub(max, -big), inf);
663 EXPECT_EQ(saturated::Sub(big, -max), inf);
664 EXPECT_EQ(saturated::Sub(max, -max), inf);
665 EXPECT_EQ(saturated::Sub(max, -inf), inf);
666 EXPECT_EQ(saturated::Sub(inf, -max), inf);
667 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
668
669 EXPECT_EQ(saturated::Sub(-big, big), -max);
670 EXPECT_EQ(saturated::Sub(-max, big), -inf);
671 EXPECT_EQ(saturated::Sub(-big, max), -inf);
672 EXPECT_EQ(saturated::Sub(-max, max), -inf);
673 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
674 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
675 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
676 }
677 {
678 const Scalar inf = std::numeric_limits<Scalar>::infinity();
679 const Scalar max = std::numeric_limits<Scalar>::max();
680 const Scalar big = max * 0.5f;
681
682 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
683 EXPECT_EQ(saturated::Sub(max, big), big);
684 EXPECT_EQ(saturated::Sub(big, max), -big);
685 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
686 EXPECT_EQ(saturated::Sub(max, inf), -inf);
687 EXPECT_EQ(saturated::Sub(inf, max), inf);
688 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
689
690 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
691 EXPECT_EQ(saturated::Sub(-max, -big), -big);
692 EXPECT_EQ(saturated::Sub(-big, -max), big);
693 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
694 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
695 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
696 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
697
698 EXPECT_EQ(saturated::Sub(big, -big), max);
699 EXPECT_EQ(saturated::Sub(max, -big), inf);
700 EXPECT_EQ(saturated::Sub(big, -max), inf);
701 EXPECT_EQ(saturated::Sub(max, -max), inf);
702 EXPECT_EQ(saturated::Sub(max, -inf), inf);
703 EXPECT_EQ(saturated::Sub(inf, -max), inf);
704 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
705
706 EXPECT_EQ(saturated::Sub(-big, big), -max);
707 EXPECT_EQ(saturated::Sub(-max, big), -inf);
708 EXPECT_EQ(saturated::Sub(-big, max), -inf);
709 EXPECT_EQ(saturated::Sub(-max, max), -inf);
710 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
711 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
712 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
713 }
714}

◆ TEST() [360/399]

impeller::testing::TEST ( SaturatedMath  ,
ImplicitSubOfSignedInts   
)

Definition at line 413 of file saturated_math_unittests.cc.

413 {
414 {
415 int8_t a = 0x79;
416 int8_t b = -5;
417 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7E));
418 a = 0x7A;
419 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7F));
420 a = 0x7B;
421 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7F));
422 }
423 {
424 int8_t a = 0x86;
425 int8_t b = 5;
426 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x81));
427 a = 0x85;
428 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x80));
429 a = 0x84;
430 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x80));
431 }
432 {
433 int16_t a = 0x7FF9;
434 int16_t b = -5;
435 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFE));
436 a = 0x7FFA;
437 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFF));
438 a = 0x7FFB;
439 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFF));
440 }
441 {
442 int16_t a = 0x8006;
443 int16_t b = 5;
444 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8001));
445 a = 0x8005;
446 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8000));
447 a = 0x8004;
448 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8000));
449 }
450 {
451 int32_t a = 0x7FFFFFF9;
452 int32_t b = -5;
453 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFE));
454 a = 0x7FFFFFFA;
455 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFF));
456 a = 0x7FFFFFFB;
457 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFF));
458 }
459 {
460 int32_t a = 0x80000006;
461 int32_t b = 5;
462 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000001));
463 a = 0x80000005;
464 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000000));
465 a = 0x80000004;
466 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000000));
467 }
468 {
469 int64_t a = 0x7FFFFFFFFFFFFFF9;
470 int64_t b = -5;
471 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFE));
472 a = 0x7FFFFFFFFFFFFFFA;
473 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
474 a = 0x7FFFFFFFFFFFFFFB;
475 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
476 }
477 {
478 int64_t a = 0x8000000000000006;
479 int64_t b = 5;
480 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000001));
481 a = 0x8000000000000005;
482 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000000));
483 a = 0x8000000000000004;
484 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000000));
485 }
486}

◆ TEST() [361/399]

impeller::testing::TEST ( ShaderArchiveTest  ,
ArchiveAndMultiArchiveHaveDifferentIdentifiers   
)

Definition at line 84 of file shader_archive_unittests.cc.

84 {
85 // The unarchiving process depends on these identifiers to check to see if its
86 // a standalone archive or a multi-archive. Things will get nutty if these are
87 // ever the same.
88 auto archive_id = fb::ShaderArchiveIdentifier();
89 auto multi_archive_id = fb::MultiArchShaderArchiveIdentifier();
90 ASSERT_EQ(std::strlen(archive_id), std::strlen(multi_archive_id));
91 ASSERT_NE(std::strncmp(archive_id, multi_archive_id, std::strlen(archive_id)),
92 0);
93}

◆ TEST() [362/399]

impeller::testing::TEST ( ShaderArchiveTest  ,
CanReadAndWriteBlobs   
)

Definition at line 33 of file shader_archive_unittests.cc.

33 {
35 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Hello",
36 CreateMappingFromString("World")));
37 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Foo",
39 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Baz",
41 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Ping",
43 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Pang",
44 CreateMappingFromString("World")));
45
46 auto mapping = writer.CreateMapping();
47 ASSERT_NE(mapping, nullptr);
48
50
51 ASSERT_TRUE(multi_writer.RegisterShaderArchive(
52 ArchiveRenderingBackend::kOpenGLES, mapping));
53
54 {
56 // Can't add the same backend again.
57 ASSERT_FALSE(multi_writer.RegisterShaderArchive(
58 ArchiveRenderingBackend::kOpenGLES, mapping));
59 }
60
61 auto multi_mapping = multi_writer.CreateMapping();
62 ASSERT_TRUE(multi_mapping);
63
64 {
66 auto no_library = MultiArchShaderArchive::CreateArchiveFromMapping(
67 multi_mapping, ArchiveRenderingBackend::kVulkan);
68 ASSERT_EQ(no_library, nullptr);
69 }
70
71 auto library = MultiArchShaderArchive::CreateArchiveFromMapping(
72 multi_mapping, ArchiveRenderingBackend::kOpenGLES);
73 ASSERT_EQ(library->GetShaderCount(), 5u);
74
75 // Wrong type.
76 ASSERT_EQ(library->GetMapping(ArchiveShaderType::kFragment, "Hello"),
77 nullptr);
78
79 auto hello_vtx = library->GetMapping(ArchiveShaderType::kVertex, "Hello");
80 ASSERT_NE(hello_vtx, nullptr);
81 ASSERT_EQ(CreateStringFromMapping(*hello_vtx), "World");
82}
bool RegisterShaderArchive(ArchiveRenderingBackend backend, std::shared_ptr< const fml::Mapping > mapping)
std::shared_ptr< fml::Mapping > CreateMapping() const
bool AddShader(ArchiveShaderType type, std::string name, std::shared_ptr< fml::Mapping > mapping)
std::shared_ptr< fml::Mapping > CreateMapping() const
static std::shared_ptr< fml::Mapping > CreateMappingFromString(std::string p_string)

◆ TEST() [363/399]

impeller::testing::TEST ( SizeTest  ,
ISizeIsEmpty   
)

Definition at line 36 of file size_unittests.cc.

36 {
37 // Non-empty
38 EXPECT_FALSE(ISize(10, 7).IsEmpty());
39
40 // Empty both width and height both 0 or negative, in all combinations
41 EXPECT_TRUE(ISize(0, 0).IsEmpty());
42 EXPECT_TRUE(ISize(-1, -1).IsEmpty());
43 EXPECT_TRUE(ISize(-1, 0).IsEmpty());
44 EXPECT_TRUE(ISize(0, -1).IsEmpty());
45
46 // Empty for 0 or negative width or height (but not both at the same time)
47 EXPECT_TRUE(ISize(10, 0).IsEmpty());
48 EXPECT_TRUE(ISize(10, -1).IsEmpty());
49 EXPECT_TRUE(ISize(0, 7).IsEmpty());
50 EXPECT_TRUE(ISize(-1, 7).IsEmpty());
51}

◆ TEST() [364/399]

impeller::testing::TEST ( SizeTest  ,
IsSquare   
)

Definition at line 53 of file size_unittests.cc.

53 {
54 EXPECT_TRUE(Size(20, 20).IsSquare());
55 EXPECT_FALSE(Size(20, 19).IsSquare());
56 EXPECT_FALSE(Size(19, 20).IsSquare());
57
58 EXPECT_TRUE(ISize(20, 20).IsSquare());
59 EXPECT_FALSE(ISize(20, 19).IsSquare());
60 EXPECT_FALSE(ISize(19, 20).IsSquare());
61}

◆ TEST() [365/399]

impeller::testing::TEST ( SizeTest  ,
MaxDimension   
)

Definition at line 63 of file size_unittests.cc.

63 {
64 EXPECT_EQ(Size(20, 20).MaxDimension(), 20);
65 EXPECT_EQ(Size(20, 19).MaxDimension(), 20);
66 EXPECT_EQ(Size(19, 20).MaxDimension(), 20);
67 EXPECT_EQ(Size(20, 21).MaxDimension(), 21);
68 EXPECT_EQ(Size(21, 20).MaxDimension(), 21);
69
70 EXPECT_EQ(ISize(20, 20).MaxDimension(), 20);
71 EXPECT_EQ(ISize(20, 19).MaxDimension(), 20);
72 EXPECT_EQ(ISize(19, 20).MaxDimension(), 20);
73 EXPECT_EQ(ISize(20, 21).MaxDimension(), 21);
74 EXPECT_EQ(ISize(21, 20).MaxDimension(), 21);
75}

◆ TEST() [366/399]

impeller::testing::TEST ( SizeTest  ,
NegationOperator   
)

Definition at line 77 of file size_unittests.cc.

77 {
78 EXPECT_EQ(-Size(10, 20), Size(-10, -20));
79 EXPECT_EQ(-Size(-10, 20), Size(10, -20));
80 EXPECT_EQ(-Size(10, -20), Size(-10, 20));
81 EXPECT_EQ(-Size(-10, -20), Size(10, 20));
82}

◆ TEST() [367/399]

impeller::testing::TEST ( SizeTest  ,
SizeIsEmpty   
)

Definition at line 12 of file size_unittests.cc.

12 {
13 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
14
15 // Non-empty
16 EXPECT_FALSE(Size(10.5, 7.2).IsEmpty());
17
18 // Empty both width and height both 0 or negative, in all combinations
19 EXPECT_TRUE(Size(0.0, 0.0).IsEmpty());
20 EXPECT_TRUE(Size(-1.0, -1.0).IsEmpty());
21 EXPECT_TRUE(Size(-1.0, 0.0).IsEmpty());
22 EXPECT_TRUE(Size(0.0, -1.0).IsEmpty());
23
24 // Empty for 0 or negative width or height (but not both at the same time)
25 EXPECT_TRUE(Size(10.5, 0.0).IsEmpty());
26 EXPECT_TRUE(Size(10.5, -1.0).IsEmpty());
27 EXPECT_TRUE(Size(0.0, 7.2).IsEmpty());
28 EXPECT_TRUE(Size(-1.0, 7.2).IsEmpty());
29
30 // Empty for NaN in width or height or both
31 EXPECT_TRUE(Size(10.5, nan).IsEmpty());
32 EXPECT_TRUE(Size(nan, 7.2).IsEmpty());
33 EXPECT_TRUE(Size(nan, nan).IsEmpty());
34}

◆ TEST() [368/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
GradientConversionNonMonotonic   
)

Definition at line 150 of file skia_conversions_unittests.cc.

150 {
151 std::vector<flutter::DlColor> colors = {
154 std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
155 const auto gradient =
157 SkPoint::Make(1.0, 1.0), //
158 4, //
159 colors.data(), //
160 stops.data(), //
162 nullptr //
163 );
164
165 std::vector<Color> converted_colors;
166 std::vector<Scalar> converted_stops;
167 skia_conversions::ConvertStops(gradient.get(), converted_colors,
168 converted_stops);
169
170 // Value is clamped to 0.5
171 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
172 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
173 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
174 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
175}
static std::shared_ptr< DlLinearGradientColorSource > MakeLinear(const SkPoint start_point, const SkPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
static constexpr SkPoint Make(float x, float y)
static constexpr DlColor kBlue()
Definition dl_color.h:26
static constexpr DlColor kRed()
Definition dl_color.h:24
static constexpr DlColor kGreen()
Definition dl_color.h:25

◆ TEST() [369/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
GradientMissing0   
)

Definition at line 72 of file skia_conversions_unittests.cc.

72 {
73 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
75 std::vector<float> stops = {0.5, 1.0};
76 const auto gradient =
78 SkPoint::Make(1.0, 1.0), //
79 2, //
80 colors.data(), //
81 stops.data(), //
83 nullptr //
84 );
85
86 std::vector<Color> converted_colors;
87 std::vector<Scalar> converted_stops;
88 skia_conversions::ConvertStops(gradient.get(), converted_colors,
89 converted_stops);
90
91 // First color is inserted as blue.
92 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
93 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
94 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
95 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
96}

◆ TEST() [370/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
GradientMissingLastValue   
)

Definition at line 98 of file skia_conversions_unittests.cc.

98 {
99 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
101 std::vector<float> stops = {0.0, .5};
102 const auto gradient =
104 SkPoint::Make(1.0, 1.0), //
105 2, //
106 colors.data(), //
107 stops.data(), //
109 nullptr //
110 );
111
112 std::vector<Color> converted_colors;
113 std::vector<Scalar> converted_stops;
114 skia_conversions::ConvertStops(gradient.get(), converted_colors,
115 converted_stops);
116
117 // Last color is inserted as red.
118 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
119 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
120 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
121 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
122}

◆ TEST() [371/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
GradientStopConversion   
)

Definition at line 46 of file skia_conversions_unittests.cc.

46 {
47 // Typical gradient.
48 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
51 std::vector<float> stops = {0.0, 0.5, 1.0};
52 const auto gradient =
54 SkPoint::Make(1.0, 1.0), //
55 3, //
56 colors.data(), //
57 stops.data(), //
59 nullptr //
60 );
61
62 std::vector<Color> converted_colors;
63 std::vector<Scalar> converted_stops;
64 skia_conversions::ConvertStops(gradient.get(), converted_colors,
65 converted_stops);
66
67 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
68 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
69 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
70}

◆ TEST() [372/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
GradientStopGreaterThan1   
)

Definition at line 124 of file skia_conversions_unittests.cc.

124 {
125 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
128 std::vector<float> stops = {0.0, 100, 1.0};
129 const auto gradient =
131 SkPoint::Make(1.0, 1.0), //
132 3, //
133 colors.data(), //
134 stops.data(), //
136 nullptr //
137 );
138
139 std::vector<Color> converted_colors;
140 std::vector<Scalar> converted_stops;
141 skia_conversions::ConvertStops(gradient.get(), converted_colors,
142 converted_stops);
143
144 // Value is clamped to 1.0
145 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
146 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
147 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
148}

◆ TEST() [373/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
SkPointToPoint   
)

Definition at line 14 of file skia_conversions_unittests.cc.

14 {
15 for (int x = -100; x < 100; x += 4) {
16 for (int y = -100; y < 100; y += 4) {
17 EXPECT_EQ(skia_conversions::ToPoint(SkPoint::Make(x * 0.25f, y * 0.25f)),
18 Point(x * 0.25f, y * 0.25f));
19 }
20 }
21}

◆ TEST() [374/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
SkPointToSize   
)

Definition at line 23 of file skia_conversions_unittests.cc.

23 {
24 for (int x = -100; x < 100; x += 4) {
25 for (int y = -100; y < 100; y += 4) {
26 EXPECT_EQ(skia_conversions::ToSize(SkPoint::Make(x * 0.25f, y * 0.25f)),
27 Size(x * 0.25f, y * 0.25f));
28 }
29 }
30}

◆ TEST() [375/399]

impeller::testing::TEST ( SkiaConversionsTest  ,
ToColor   
)

Definition at line 32 of file skia_conversions_unittests.cc.

32 {
33 // Create a color with alpha, red, green, and blue values that are all
34 // trivially divisible by 255 so that we can test the conversion results in
35 // correct scalar values.
36 // AARRGGBB
37 const flutter::DlColor color = flutter::DlColor(0x8040C020);
38 auto converted_color = skia_conversions::ToColor(color);
39
40 ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
41 ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
42 ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
43 ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
44}

◆ TEST() [376/399]

impeller::testing::TEST ( SpecConstant  ,
CanCreateShaderWithSpecializationConstant   
)

Definition at line 14 of file specialization_constants_unittests.cc.

14 {
15 auto mock_gles = MockGLES::Init();
16 auto& proc_table = mock_gles->GetProcTable();
17 auto shader_source =
18 "#version 100\n"
19 "#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
20 "#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
21 "#endif\n"
22 "void main() { return vec4(0.0); }";
23 auto test_shader = std::make_shared<fml::DataMapping>(shader_source);
24
25 auto result = proc_table.ComputeShaderWithDefines(*test_shader, {0});
26
27 auto expected_shader_source =
28 "#version 100\n"
29 "#define SPIRV_CROSS_CONSTANT_ID_0 0.000000\n"
30 "#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
31 "#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
32 "#endif\n"
33 "void main() { return vec4(0.0); }";
34
35 if (!result.has_value()) {
36 GTEST_FAIL() << "Expected shader source";
37 }
38 ASSERT_EQ(result.value(), expected_shader_source);
39}

◆ TEST() [377/399]

impeller::testing::TEST ( SpecConstant  ,
CanCreateShaderWithSpecializationConstantMultipleValues   
)

Definition at line 41 of file specialization_constants_unittests.cc.

41 {
42 auto mock_gles = MockGLES::Init();
43 auto& proc_table = mock_gles->GetProcTable();
44 auto shader_source =
45 "#version 100\n"
46 "#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
47 "#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
48 "#endif\n"
49 "void main() { return vec4(0.0); }";
50 auto test_shader = std::make_shared<fml::DataMapping>(shader_source);
51
52 auto result =
53 proc_table.ComputeShaderWithDefines(*test_shader, {0, 1, 2, 3, 4, 5});
54
55 auto expected_shader_source =
56 "#version 100\n"
57 "#define SPIRV_CROSS_CONSTANT_ID_0 0.000000\n"
58 "#define SPIRV_CROSS_CONSTANT_ID_1 1.000000\n"
59 "#define SPIRV_CROSS_CONSTANT_ID_2 2.000000\n"
60 "#define SPIRV_CROSS_CONSTANT_ID_3 3.000000\n"
61 "#define SPIRV_CROSS_CONSTANT_ID_4 4.000000\n"
62 "#define SPIRV_CROSS_CONSTANT_ID_5 5.000000\n"
63 "#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
64 "#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
65 "#endif\n"
66 "void main() { return vec4(0.0); }";
67
68 if (!result.has_value()) {
69 GTEST_FAIL() << "Expected shader source";
70 }
71 ASSERT_EQ(result.value(), expected_shader_source);
72}

◆ TEST() [378/399]

impeller::testing::TEST ( StringsTest  ,
CanSPrintF   
)

Definition at line 86 of file base_unittests.cc.

86 {
87 ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
88 ASSERT_EQ(SPrintF(""), "");
89 ASSERT_EQ(SPrintF("Hello"), "Hello");
90 ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
91}
std::string SPrintF(const char *format,...)
Definition strings.cc:12

◆ TEST() [379/399]

impeller::testing::TEST ( SwapchainTest  ,
CachesRenderPassOnSwapchainImage   
)

Definition at line 58 of file swapchain_unittests.cc.

58 {
59 auto const context = MockVulkanContextBuilder().Build();
60
61 auto surface = CreateSurface(*context);
62 auto swapchain =
63 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1});
64
65 EXPECT_TRUE(swapchain->IsValid());
66
67 // The mock swapchain will always create 3 images, verify each one starts
68 // out with the same MSAA and depth+stencil texture, and no cached
69 // framebuffer.
70 std::vector<std::shared_ptr<Texture>> msaa_textures;
71 std::vector<std::shared_ptr<Texture>> depth_stencil_textures;
72 for (auto i = 0u; i < 3u; i++) {
73 auto drawable = swapchain->AcquireNextDrawable();
74 RenderTarget render_target = drawable->GetTargetRenderPassDescriptor();
75
76 auto texture = render_target.GetRenderTargetTexture();
77 auto& texture_vk = TextureVK::Cast(*texture);
78 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), nullptr);
79 EXPECT_EQ(texture_vk.GetCachedRenderPass(), nullptr);
80
81 auto command_buffer = context->CreateCommandBuffer();
82 auto render_pass = command_buffer->CreateRenderPass(render_target);
83 render_pass->EncodeCommands();
84
85 auto& depth = render_target.GetDepthAttachment();
86 depth_stencil_textures.push_back(depth.has_value() ? depth->texture
87 : nullptr);
88 msaa_textures.push_back(
89 render_target.GetColorAttachments().find(0u)->second.texture);
90 }
91
92 for (auto i = 1; i < 3; i++) {
93 EXPECT_EQ(msaa_textures[i - 1], msaa_textures[i]);
94 EXPECT_EQ(depth_stencil_textures[i - 1], depth_stencil_textures[i]);
95 }
96
97 // After each images has been acquired once and the render pass presented,
98 // each should have a cached framebuffer and render pass.
99
100 std::vector<SharedHandleVK<vk::Framebuffer>> framebuffers;
101 std::vector<SharedHandleVK<vk::RenderPass>> render_passes;
102 for (auto i = 0u; i < 3u; i++) {
103 auto drawable = swapchain->AcquireNextDrawable();
104 RenderTarget render_target = drawable->GetTargetRenderPassDescriptor();
105
106 auto texture = render_target.GetRenderTargetTexture();
107 auto& texture_vk = TextureVK::Cast(*texture);
108
109 EXPECT_NE(texture_vk.GetCachedFramebuffer(), nullptr);
110 EXPECT_NE(texture_vk.GetCachedRenderPass(), nullptr);
111 framebuffers.push_back(texture_vk.GetCachedFramebuffer());
112 render_passes.push_back(texture_vk.GetCachedRenderPass());
113 }
114
115 // Iterate through once more to verify render passes and framebuffers are
116 // unchanged.
117 for (auto i = 0u; i < 3u; i++) {
118 auto drawable = swapchain->AcquireNextDrawable();
119 RenderTarget render_target = drawable->GetTargetRenderPassDescriptor();
120
121 auto texture = render_target.GetRenderTargetTexture();
122 auto& texture_vk = TextureVK::Cast(*texture);
123
124 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), framebuffers[i]);
125 EXPECT_EQ(texture_vk.GetCachedRenderPass(), render_passes[i]);
126 }
127}
std::shared_ptr< Texture > GetRenderTargetTexture() const
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
const std::optional< DepthAttachment > & GetDepthAttachment() const
VkSwapchainKHR swapchain
Definition main.cc:64
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
vk::UniqueSurfaceKHR CreateSurface(const ContextVK &context)

◆ TEST() [380/399]

impeller::testing::TEST ( SwapchainTest  ,
CanCreateSwapchain   
)

Definition at line 28 of file swapchain_unittests.cc.

28 {
29 auto const context = MockVulkanContextBuilder().Build();
30
31 auto surface = CreateSurface(*context);
32 auto swapchain =
33 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1});
34
35 EXPECT_TRUE(swapchain->IsValid());
36}

◆ TEST() [381/399]

impeller::testing::TEST ( SwapchainTest  ,
RecreateSwapchainWhenSizeChanges   
)

Definition at line 38 of file swapchain_unittests.cc.

38 {
39 auto const context = MockVulkanContextBuilder().Build();
40
41 auto surface = CreateSurface(*context);
43 auto swapchain =
44 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1},
45 /*enable_msaa=*/false);
46 auto image = swapchain->AcquireNextDrawable();
47 auto expected_size = ISize{1, 1};
48 EXPECT_EQ(image->GetSize(), expected_size);
49
50 SetSwapchainImageSize(ISize{100, 100});
51 swapchain->UpdateSurfaceSize(ISize{100, 100});
52
53 auto image_b = swapchain->AcquireNextDrawable();
54 expected_size = ISize{100, 100};
55 EXPECT_EQ(image_b->GetSize(), expected_size);
56}
sk_sp< SkImage > image
Definition examples.cpp:29
void SetSwapchainImageSize(ISize size)
Override the image size returned by all swapchain images.

◆ TEST() [382/399]

impeller::testing::TEST ( TessellatorTest  ,
ChecksConcurrentPolylineUsage   
)

Definition at line 483 of file tessellator_unittests.cc.

483 {
484 auto tessellator = std::make_shared<Tessellator>();
485 PathBuilder builder;
486 builder.AddLine({0, 0}, {100, 100});
487 auto path = builder.TakePath();
488
489 auto polyline = tessellator->CreateTempPolyline(path, 0.1);
490 EXPECT_DEBUG_DEATH(tessellator->CreateTempPolyline(path, 0.1),
491 "point_buffer_");
492}

◆ TEST() [383/399]

impeller::testing::TEST ( TessellatorTest  ,
CircleVertexCounts   
)

Definition at line 109 of file tessellator_unittests.cc.

109 {
110 auto tessellator = std::make_shared<Tessellator>();
111
112 auto test = [&tessellator](const Matrix& transform, Scalar radius) {
113 auto generator = tessellator->FilledCircle(transform, {}, radius);
114 size_t quadrant_divisions = generator.GetVertexCount() / 4;
115
116 // Confirm the approximation error is within the currently accepted
117 // |kCircleTolerance| value advertised by |CircleTessellator|.
118 // (With an additional 1% tolerance for floating point rounding.)
119 double angle = kPiOver2 / quadrant_divisions;
120 Point first = {radius, 0};
121 Point next = {static_cast<Scalar>(cos(angle) * radius),
122 static_cast<Scalar>(sin(angle) * radius)};
123 Point midpoint = (first + next) * 0.5;
124 EXPECT_GE(midpoint.GetLength(),
125 radius - Tessellator::kCircleTolerance * 1.01)
126 << ", transform = " << transform << ", radius = " << radius
127 << ", divisions = " << quadrant_divisions;
128 };
129
130 test({}, 0.0);
131 test({}, 0.9);
132 test({}, 1.0);
133 test({}, 1.9);
134 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 0.95);
135 test({}, 2.0);
136 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 1.0);
137 test({}, 11.9);
138 test({}, 12.0);
139 test({}, 35.9);
140 for (int i = 36; i < 10000; i += 4) {
141 test({}, i);
142 }
143}
static float next(float f)
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47

◆ TEST() [384/399]

impeller::testing::TEST ( TessellatorTest  ,
EarlyReturnEmptyConvexShape   
)

Definition at line 469 of file tessellator_unittests.cc.

469 {
470 // This path is not technically empty (it has a size in one dimension),
471 // but is otherwise completely flat.
472 auto tessellator = std::make_shared<Tessellator>();
473 PathBuilder builder;
474 builder.MoveTo({0, 0});
475 builder.MoveTo({10, 10}, /*relative=*/true);
476
477 auto points = tessellator->TessellateConvex(builder.TakePath(), 3.0);
478
479 EXPECT_TRUE(points.empty());
480}

◆ TEST() [385/399]

impeller::testing::TEST ( TessellatorTest  ,
FilledCircleTessellationVertices   
)

Definition at line 145 of file tessellator_unittests.cc.

145 {
146 auto tessellator = std::make_shared<Tessellator>();
147
148 auto test = [&tessellator](const Matrix& transform, const Point& center,
149 Scalar radius) {
150 auto generator = tessellator->FilledCircle(transform, center, radius);
151 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
152
153 auto vertex_count = generator.GetVertexCount();
154 auto vertices = std::vector<Point>();
155 generator.GenerateVertices([&vertices](const Point& p) { //
156 vertices.push_back(p);
157 });
158 EXPECT_EQ(vertices.size(), vertex_count);
159 ASSERT_EQ(vertex_count % 4, 0u);
160
161 auto quadrant_count = vertex_count / 4;
162 for (size_t i = 0; i < quadrant_count; i++) {
163 double angle = kPiOver2 * i / (quadrant_count - 1);
164 double degrees = angle * 180.0 / kPi;
165 double rsin = sin(angle) * radius;
166 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
167 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radius;
168 EXPECT_POINT_NEAR(vertices[i * 2],
169 Point(center.x - rcos, center.y + rsin))
170 << "vertex " << i << ", angle = " << degrees << std::endl;
171 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
172 Point(center.x - rcos, center.y - rsin))
173 << "vertex " << i << ", angle = " << degrees << std::endl;
174 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
175 Point(center.x + rcos, center.y - rsin))
176 << "vertex " << i << ", angle = " << degrees << std::endl;
177 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
178 Point(center.x + rcos, center.y + rsin))
179 << "vertex " << i << ", angle = " << degrees << std::endl;
180 }
181 };
182
183 test({}, {}, 2.0);
184 test({}, {10, 10}, 2.0);
185 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0);
186 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0);
187}
static SkScalar center(float pos0, float pos1)

◆ TEST() [386/399]

impeller::testing::TEST ( TessellatorTest  ,
FilledEllipseTessellationVertices   
)

Definition at line 334 of file tessellator_unittests.cc.

334 {
335 auto tessellator = std::make_shared<Tessellator>();
336
337 auto test = [&tessellator](const Matrix& transform, const Rect& bounds) {
338 auto center = bounds.GetCenter();
339 auto half_size = bounds.GetSize() * 0.5f;
340
341 auto generator = tessellator->FilledEllipse(transform, bounds);
342 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
343
344 auto vertex_count = generator.GetVertexCount();
345 auto vertices = std::vector<Point>();
346 generator.GenerateVertices([&vertices](const Point& p) { //
347 vertices.push_back(p);
348 });
349 EXPECT_EQ(vertices.size(), vertex_count);
350 ASSERT_EQ(vertex_count % 4, 0u);
351
352 auto quadrant_count = vertex_count / 4;
353 for (size_t i = 0; i < quadrant_count; i++) {
354 double angle = kPiOver2 * i / (quadrant_count - 1);
355 double degrees = angle * 180.0 / kPi;
356 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
357 double rcos =
358 (i == quadrant_count - 1) ? 0.0f : cos(angle) * half_size.width;
359 double rsin = sin(angle) * half_size.height;
360 EXPECT_POINT_NEAR(vertices[i * 2],
361 Point(center.x - rcos, center.y + rsin))
362 << "vertex " << i << ", angle = " << degrees << ", " //
363 << "bounds = " << bounds << std::endl;
364 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
365 Point(center.x - rcos, center.y - rsin))
366 << "vertex " << i << ", angle = " << degrees << ", " //
367 << "bounds = " << bounds << std::endl;
368 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
369 Point(center.x + rcos, center.y - rsin))
370 << "vertex " << i << ", angle = " << degrees << ", " //
371 << "bounds = " << bounds << std::endl;
372 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
373 Point(center.x + rcos, center.y + rsin))
374 << "vertex " << i << ", angle = " << degrees << ", " //
375 << "bounds = " << bounds << std::endl;
376 }
377 };
378
379 // Square bounds should actually use the circle generator, but its
380 // results should match the same math as the ellipse generator.
381 test({}, Rect::MakeXYWH(0, 0, 2, 2));
382
383 test({}, Rect::MakeXYWH(0, 0, 2, 3));
384 test({}, Rect::MakeXYWH(0, 0, 3, 2));
385 test({}, Rect::MakeXYWH(5, 10, 2, 3));
386 test({}, Rect::MakeXYWH(16, 7, 3, 2));
387 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 3, 2));
388 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 2, 3));
389 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
390 Rect::MakeXYWH(5000, 10000, 3000, 2000));
391 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
392 Rect::MakeXYWH(5000, 10000, 2000, 3000));
393}
int32_t width

◆ TEST() [387/399]

impeller::testing::TEST ( TessellatorTest  ,
FilledRoundRectTessellationVertices   
)

Definition at line 395 of file tessellator_unittests.cc.

395 {
396 auto tessellator = std::make_shared<Tessellator>();
397
398 auto test = [&tessellator](const Matrix& transform, const Rect& bounds,
399 const Size& radii) {
400 FML_DCHECK(radii.width * 2 <= bounds.GetWidth()) << radii << bounds;
401 FML_DCHECK(radii.height * 2 <= bounds.GetHeight()) << radii << bounds;
402
403 Scalar middle_left = bounds.GetX() + radii.width;
404 Scalar middle_top = bounds.GetY() + radii.height;
405 Scalar middle_right = bounds.GetX() + bounds.GetWidth() - radii.width;
406 Scalar middle_bottom = bounds.GetY() + bounds.GetHeight() - radii.height;
407
408 auto generator = tessellator->FilledRoundRect(transform, bounds, radii);
409 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
410
411 auto vertex_count = generator.GetVertexCount();
412 auto vertices = std::vector<Point>();
413 generator.GenerateVertices([&vertices](const Point& p) { //
414 vertices.push_back(p);
415 });
416 EXPECT_EQ(vertices.size(), vertex_count);
417 ASSERT_EQ(vertex_count % 4, 0u);
418
419 auto quadrant_count = vertex_count / 4;
420 for (size_t i = 0; i < quadrant_count; i++) {
421 double angle = kPiOver2 * i / (quadrant_count - 1);
422 double degrees = angle * 180.0 / kPi;
423 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
424 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radii.width;
425 double rsin = sin(angle) * radii.height;
426 EXPECT_POINT_NEAR(vertices[i * 2],
427 Point(middle_left - rcos, middle_bottom + rsin))
428 << "vertex " << i << ", angle = " << degrees << ", " //
429 << "bounds = " << bounds << std::endl;
430 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
431 Point(middle_left - rcos, middle_top - rsin))
432 << "vertex " << i << ", angle = " << degrees << ", " //
433 << "bounds = " << bounds << std::endl;
434 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
435 Point(middle_right + rcos, middle_top - rsin))
436 << "vertex " << i << ", angle = " << degrees << ", " //
437 << "bounds = " << bounds << std::endl;
438 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
439 Point(middle_right + rcos, middle_bottom + rsin))
440 << "vertex " << i << ", angle = " << degrees << ", " //
441 << "bounds = " << bounds << std::endl;
442 }
443 };
444
445 // Both radii spanning the bounds should actually use the circle/ellipse
446 // generator, but their results should match the same math as the round
447 // rect generator.
448 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 10});
449
450 // One radius spanning the bounds, but not the other will not match the
451 // round rect math if the generator transfers to circle/ellipse
452 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 5});
453 test({}, Rect::MakeXYWH(0, 0, 20, 20), {5, 10});
454
455 test({}, Rect::MakeXYWH(0, 0, 20, 30), {2, 2});
456 test({}, Rect::MakeXYWH(0, 0, 30, 20), {2, 2});
457 test({}, Rect::MakeXYWH(5, 10, 20, 30), {2, 3});
458 test({}, Rect::MakeXYWH(16, 7, 30, 20), {2, 3});
459 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 30, 20),
460 {2, 3});
461 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 20, 30),
462 {2, 3});
463 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
464 Rect::MakeXYWH(5000, 10000, 3000, 2000), {50, 70});
465 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
466 Rect::MakeXYWH(5000, 10000, 2000, 3000), {50, 70});
467}

◆ TEST() [388/399]

impeller::testing::TEST ( TessellatorTest  ,
RoundCapLineTessellationVertices   
)

Definition at line 261 of file tessellator_unittests.cc.

261 {
262 auto tessellator = std::make_shared<Tessellator>();
263
264 auto test = [&tessellator](const Matrix& transform, const Point& p0,
265 const Point& p1, Scalar radius) {
266 auto generator = tessellator->RoundCapLine(transform, p0, p1, radius);
267 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
268
269 auto vertex_count = generator.GetVertexCount();
270 auto vertices = std::vector<Point>();
271 generator.GenerateVertices([&vertices](const Point& p) { //
272 vertices.push_back(p);
273 });
274 EXPECT_EQ(vertices.size(), vertex_count);
275 ASSERT_EQ(vertex_count % 4, 0u);
276
277 Point along = p1 - p0;
278 Scalar length = along.GetLength();
279 if (length > 0) {
280 along *= radius / length;
281 } else {
282 along = {radius, 0};
283 }
284 Point across = {-along.y, along.x};
285
286 auto quadrant_count = vertex_count / 4;
287 for (size_t i = 0; i < quadrant_count; i++) {
288 double angle = kPiOver2 * i / (quadrant_count - 1);
289 double degrees = angle * 180.0 / kPi;
290 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
291 Point relative_along =
292 along * ((i == quadrant_count - 1) ? 0.0f : cos(angle));
293 Point relative_across = across * sin(angle);
294 EXPECT_POINT_NEAR(vertices[i * 2], //
295 p0 - relative_along + relative_across)
296 << "vertex " << i << ", angle = " << degrees << ", " //
297 << "line = " << p0 << " => " << p1 << ", " //
298 << "radius = " << radius << std::endl;
299 EXPECT_POINT_NEAR(vertices[i * 2 + 1], //
300 p0 - relative_along - relative_across)
301 << "vertex " << i << ", angle = " << degrees << ", " //
302 << "line = " << p0 << " => " << p1 << ", " //
303 << "radius = " << radius << std::endl;
304 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1], //
305 p1 + relative_along - relative_across)
306 << "vertex " << i << ", angle = " << degrees << ", " //
307 << "line = " << p0 << " => " << p1 << ", " //
308 << "radius = " << radius << std::endl;
309 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2], //
310 p1 + relative_along + relative_across)
311 << "vertex " << i << ", angle = " << degrees << ", " //
312 << "line = " << p0 << " => " << p1 << ", " //
313 << "radius = " << radius << std::endl;
314 }
315 };
316
317 // Empty line should actually use the circle generator, but its
318 // results should match the same math as the round cap generator.
319 test({}, {0, 0}, {0, 0}, 10);
320
321 test({}, {0, 0}, {10, 0}, 2);
322 test({}, {10, 0}, {0, 0}, 2);
323 test({}, {0, 0}, {10, 10}, 2);
324
325 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 0}, 2);
326 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {10, 0}, {0, 0}, 2);
327 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 10}, 2);
328
329 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 0}, 2);
330 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {10, 0}, {0, 0}, 2);
331 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 10}, 2);
332}
size_t length
constexpr Type GetLength() const
Definition point.h:206

◆ TEST() [389/399]

impeller::testing::TEST ( TessellatorTest  ,
StrokedCircleTessellationVertices   
)

Definition at line 189 of file tessellator_unittests.cc.

189 {
190 auto tessellator = std::make_shared<Tessellator>();
191
192 auto test = [&tessellator](const Matrix& transform, const Point& center,
193 Scalar radius, Scalar half_width) {
194 ASSERT_GT(radius, half_width);
195 auto generator =
196 tessellator->StrokedCircle(transform, center, radius, half_width);
197 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
198
199 auto vertex_count = generator.GetVertexCount();
200 auto vertices = std::vector<Point>();
201 generator.GenerateVertices([&vertices](const Point& p) { //
202 vertices.push_back(p);
203 });
204 EXPECT_EQ(vertices.size(), vertex_count);
205 ASSERT_EQ(vertex_count % 4, 0u);
206
207 auto quadrant_count = vertex_count / 8;
208
209 // Test outer points first
210 for (size_t i = 0; i < quadrant_count; i++) {
211 double angle = kPiOver2 * i / (quadrant_count - 1);
212 double degrees = angle * 180.0 / kPi;
213 double rsin = sin(angle) * (radius + half_width);
214 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
215 double rcos =
216 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius + half_width);
217 EXPECT_POINT_NEAR(vertices[i * 2],
218 Point(center.x - rcos, center.y - rsin))
219 << "vertex " << i << ", angle = " << degrees << std::endl;
220 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2],
221 Point(center.x + rsin, center.y - rcos))
222 << "vertex " << i << ", angle = " << degrees << std::endl;
223 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2],
224 Point(center.x + rcos, center.y + rsin))
225 << "vertex " << i << ", angle = " << degrees << std::endl;
226 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2],
227 Point(center.x - rsin, center.y + rcos))
228 << "vertex " << i << ", angle = " << degrees << std::endl;
229 }
230
231 // Then test innerer points
232 for (size_t i = 0; i < quadrant_count; i++) {
233 double angle = kPiOver2 * i / (quadrant_count - 1);
234 double degrees = angle * 180.0 / kPi;
235 double rsin = sin(angle) * (radius - half_width);
236 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
237 double rcos =
238 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius - half_width);
239 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
240 Point(center.x - rcos, center.y - rsin))
241 << "vertex " << i << ", angle = " << degrees << std::endl;
242 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2 + 1],
243 Point(center.x + rsin, center.y - rcos))
244 << "vertex " << i << ", angle = " << degrees << std::endl;
245 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2 + 1],
246 Point(center.x + rcos, center.y + rsin))
247 << "vertex " << i << ", angle = " << degrees << std::endl;
248 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2 + 1],
249 Point(center.x - rsin, center.y + rcos))
250 << "vertex " << i << ", angle = " << degrees << std::endl;
251 }
252 };
253
254 test({}, {}, 2.0, 1.0);
255 test({}, {}, 2.0, 0.5);
256 test({}, {10, 10}, 2.0, 1.0);
257 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0, 1.0);
258 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0, 10.0);
259}

◆ TEST() [390/399]

impeller::testing::TEST ( TessellatorTest  ,
TessellateConvex   
)

Definition at line 83 of file tessellator_unittests.cc.

83 {
84 {
86 // Sanity check simple rectangle.
87 auto pts = t.TessellateConvex(
88 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 10, 10)).TakePath(), 1.0);
89
90 std::vector<Point> expected = {{0, 0}, {10, 0}, {0, 10}, {10, 10}};
91 EXPECT_EQ(pts, expected);
92 }
93
94 {
95 Tessellator t;
96 auto pts = t.TessellateConvex(PathBuilder{}
97 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
98 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
99 .TakePath(),
100 1.0);
101
102 std::vector<Point> expected = {{0, 0}, {10, 0}, {0, 10}, {10, 10},
103 {10, 10}, {20, 20}, {20, 20}, {30, 20},
104 {20, 30}, {30, 30}};
105 EXPECT_EQ(pts, expected);
106 }
107}
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Definition tessellator.h:29
std::vector< Point > TessellateConvex(const Path &path, Scalar tolerance)
Given a convex path, create a triangle fan structure.

◆ TEST() [391/399]

impeller::testing::TEST ( TessellatorTest  ,
TessellatorBuilderReturnsCorrectResultStatus   
)

Definition at line 16 of file tessellator_unittests.cc.

16 {
17 // Zero points.
18 {
20 auto path = PathBuilder{}.TakePath(FillType::kOdd);
22 path, 1.0f,
23 [](const float* vertices, size_t vertices_count,
24 const uint16_t* indices, size_t indices_count) { return true; });
25
26 ASSERT_EQ(result, Tessellator::Result::kInputError);
27 }
28
29 // One point.
30 {
31 TessellatorLibtess t;
32 auto path = PathBuilder{}.LineTo({0, 0}).TakePath(FillType::kOdd);
33 Tessellator::Result result = t.Tessellate(
34 path, 1.0f,
35 [](const float* vertices, size_t vertices_count,
36 const uint16_t* indices, size_t indices_count) { return true; });
37
38 ASSERT_EQ(result, Tessellator::Result::kSuccess);
39 }
40
41 // Two points.
42 {
43 TessellatorLibtess t;
44 auto path = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kOdd);
45 Tessellator::Result result = t.Tessellate(
46 path, 1.0f,
47 [](const float* vertices, size_t vertices_count,
48 const uint16_t* indices, size_t indices_count) { return true; });
49
50 ASSERT_EQ(result, Tessellator::Result::kSuccess);
51 }
52
53 // Many points.
54 {
55 TessellatorLibtess t;
56 PathBuilder builder;
57 for (int i = 0; i < 1000; i++) {
58 auto coord = i * 1.0f;
59 builder.AddLine({coord, coord}, {coord + 1, coord + 1});
60 }
61 auto path = builder.TakePath(FillType::kOdd);
62 Tessellator::Result result = t.Tessellate(
63 path, 1.0f,
64 [](const float* vertices, size_t vertices_count,
65 const uint16_t* indices, size_t indices_count) { return true; });
66
67 ASSERT_EQ(result, Tessellator::Result::kSuccess);
68 }
69
70 // Closure fails.
71 {
72 TessellatorLibtess t;
73 auto path = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kOdd);
74 Tessellator::Result result = t.Tessellate(
75 path, 1.0f,
76 [](const float* vertices, size_t vertices_count,
77 const uint16_t* indices, size_t indices_count) { return false; });
78
79 ASSERT_EQ(result, Tessellator::Result::kInputError);
80 }
81}
An extended tessellator that offers arbitrary/concave tessellation via the libtess2 library.
Tessellator::Result Tessellate(const Path &path, Scalar tolerance, const BuilderCallback &callback)
Generates filled triangles from the path. A callback is invoked once for the entire tessellation.

◆ TEST() [392/399]

impeller::testing::TEST ( TextureMTL  ,
CreateFromDrawable   
)

Definition at line 21 of file texture_mtl_unittests.mm.

21 {
22 auto device = MTLCreateSystemDefaultDevice();
23 auto layer = [[CAMetalLayer alloc] init];
24 layer.device = device;
25 layer.drawableSize = CGSize{100, 100};
26 layer.pixelFormat = ToMTLPixelFormat(PixelFormat::kB8G8R8A8UNormInt);
27
29 desc.size = {100, 100};
30 desc.format = PixelFormat::kB8G8R8A8UNormInt;
31 auto drawable_future = GetDrawableDeferred(layer);
32 auto drawable_texture =
33 CreateTextureFromDrawableFuture(desc, drawable_future);
34
35 ASSERT_TRUE(drawable_texture->IsValid());
36 EXPECT_TRUE(drawable_texture->IsDrawable());
37
38 // Spawn a thread and acquire the drawable in the thread.
39 auto thread = std::thread([&drawable_texture]() {
40 // Force the drawable to be acquired.
41 drawable_texture->GetMTLTexture();
42 });
43 thread.join();
44 // Block until drawable is acquired.
45 EXPECT_TRUE(drawable_future.get() != nil);
46 // Drawable is cached.
47 EXPECT_TRUE(drawable_texture->GetMTLTexture() != nil);
48 // Once more for good measure.
49 EXPECT_TRUE(drawable_texture->GetMTLTexture() != nil);
50}
constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format)
Definition formats_mtl.h:77

◆ TEST() [393/399]

impeller::testing::TEST ( ThreadTest  ,
CanCreateMutex   
)

Definition at line 36 of file base_unittests.cc.

36 {
37 Foo f = {};
38
39 // f.a = 100; <--- Static analysis error.
40 f.mtx.Lock();
41 f.a = 100;
42 f.mtx.Unlock();
43}

◆ TEST() [394/399]

impeller::testing::TEST ( ThreadTest  ,
CanCreateMutexLock   
)

Definition at line 45 of file base_unittests.cc.

45 {
46 Foo f = {};
47
48 // f.a = 100; <--- Static analysis error.
49 auto a = Lock(f.mtx);
50 f.a = 100;
51}

◆ TEST() [395/399]

impeller::testing::TEST ( ThreadTest  ,
CanCreateRWMutex   
)

Definition at line 53 of file base_unittests.cc.

53 {
54 RWFoo f = {};
55
56 // f.a = 100; <--- Static analysis error.
57 f.mtx.LockWriter();
58 f.a = 100;
59 f.mtx.UnlockWriter();
60 // int b = f.a; <--- Static analysis error.
61 f.mtx.LockReader();
62 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
64 f.mtx.UnlockReader();
65}
#define FML_ALLOW_UNUSED_LOCAL(x)

◆ TEST() [396/399]

impeller::testing::TEST ( ThreadTest  ,
CanCreateRWMutexLock   
)

Definition at line 67 of file base_unittests.cc.

67 {
68 RWFoo f = {};
69
70 // f.a = 100; <--- Static analysis error.
71 {
72 auto write_lock = WriterLock{f.mtx};
73 f.a = 100;
74 }
75
76 // int b = f.a; <--- Static analysis error.
77 {
78 auto read_lock = ReaderLock(f.mtx);
79 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
81 }
82
83 // f.mtx.UnlockReader(); <--- Static analysis error.
84}

◆ TEST() [397/399]

impeller::testing::TEST ( TraceSerializer  ,
Save   
)

Definition at line 11 of file trace_serializer_unittests.cc.

11 {
12 CanvasRecorder<TraceSerializer> recorder;
13 std::ostringstream ss;
15 recorder.Save();
16 ASSERT_TRUE(ss.str().size() > 0);
17}
static void CaptureNextLog(std::ostringstream *stream)
Definition logging.cc:129

◆ TEST() [398/399]

impeller::testing::TEST ( TrigTest  ,
MultiplyByScalarRadius   
)

Definition at line 65 of file trig_unittests.cc.

65 {
66 for (int i = 0; i <= 360; i++) {
67 for (int i = 1; i <= 10; i++) {
68 Scalar radius = i * 5.0f;
69 EXPECT_EQ(Trig(Degrees(i)) * radius,
70 Point(radius * std::cos(i * kPi / 180),
71 radius * std::sin(i * kPi / 180)))
72 << "at " << i << " degrees and radius " << radius;
73 }
74 }
75}
A structure to store the sine and cosine of an angle.
Definition trig.h:16

◆ TEST() [399/399]

impeller::testing::TEST ( TrigTest  ,
TrigAngles   
)

Definition at line 15 of file trig_unittests.cc.

15 {
16 {
17 Trig trig(Degrees(0.0));
18 EXPECT_EQ(trig.cos, 1.0);
19 EXPECT_EQ(trig.sin, 0.0);
20 }
21
22 {
23 Trig trig(Radians(0.0));
24 EXPECT_EQ(trig.cos, 1.0);
25 EXPECT_EQ(trig.sin, 0.0);
26 }
27
28 {
29 Trig trig(Degrees(30.0));
30 EXPECT_NEAR(trig.cos, sqrt(0.75), kEhCloseEnough);
31 EXPECT_NEAR(trig.sin, 0.5, kEhCloseEnough);
32 }
33
34 {
35 Trig trig(Radians(kPi / 6.0));
36 EXPECT_NEAR(trig.cos, sqrt(0.75), kEhCloseEnough);
37 EXPECT_NEAR(trig.sin, 0.5, kEhCloseEnough);
38 }
39
40 {
41 Trig trig(Degrees(60.0));
42 EXPECT_NEAR(trig.cos, 0.5, kEhCloseEnough);
43 EXPECT_NEAR(trig.sin, sqrt(0.75), kEhCloseEnough);
44 }
45
46 {
47 Trig trig(Radians(kPi / 3.0));
48 EXPECT_NEAR(trig.cos, 0.5, kEhCloseEnough);
49 EXPECT_NEAR(trig.sin, sqrt(0.75), kEhCloseEnough);
50 }
51
52 {
53 Trig trig(Degrees(90.0));
54 EXPECT_NEAR(trig.cos, 0.0, kEhCloseEnough);
55 EXPECT_NEAR(trig.sin, 1.0, kEhCloseEnough);
56 }
57
58 {
59 Trig trig(Radians(kPi / 2.0));
60 EXPECT_NEAR(trig.cos, 0.0, kEhCloseEnough);
61 EXPECT_NEAR(trig.sin, 1.0, kEhCloseEnough);
62 }
63}
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition SkVx.h:706

◆ TEST_F()

impeller::testing::TEST_F ( GoldenTests  ,
ConicalGradient   
)

Definition at line 72 of file golden_tests.cc.

72 {
73 Canvas canvas;
75
76 paint.color_source = ColorSource::MakeConicalGradient(
77 {125, 125}, 125, {Color(1.0, 0.0, 0.0, 1.0), Color(0.0, 0.0, 1.0, 1.0)},
78 {0, 1}, {180, 180}, 0, Entity::TileMode::kClamp, {});
79
80 paint.stroke_width = 0.0;
81 paint.style = Paint::Style::kFill;
82 canvas.DrawRect(Rect::MakeXYWH(10, 10, 250, 250), paint);
84
85 auto aiks_context =
86 AiksContext(Screenshotter().GetPlayground().GetContext(), nullptr);
87 auto screenshot = Screenshotter().MakeScreenshot(aiks_context, picture);
88 ASSERT_TRUE(SaveScreenshot(std::move(screenshot)));
89}
SK_API GrDirectContext * GetContext(const SkImage *src)
sk_sp< const SkPicture > picture
Definition SkRecords.h:299
SK_API sk_sp< PrecompileShader > Picture()

◆ TEST_P() [1/435]

impeller::testing::TEST_P ( AiksTest  ,
ArcWithZeroSweepAndBlur   
)

Definition at line 365 of file aiks_path_unittests.cc.

365 {
366 Canvas canvas;
367 canvas.Scale(GetContentScale());
368
369 Paint paint;
370 paint.color = Color::Red();
371 std::vector<Color> colors = {Color{1.0, 0.0, 0.0, 1.0},
372 Color{0.0, 0.0, 0.0, 1.0}};
373 std::vector<Scalar> stops = {0.0, 1.0};
374 paint.color_source = ColorSource::MakeSweepGradient(
375 {100, 100}, Degrees(45), Degrees(135), std::move(colors),
376 std::move(stops), Entity::TileMode::kMirror, {});
377 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
378 .style = FilterContents::BlurStyle::kNormal,
379 .sigma = Sigma(20),
380 };
381
382 PathBuilder builder;
383 builder.AddArc(Rect::MakeXYWH(10, 10, 100, 100), Degrees(0), Degrees(0),
384 false);
385 canvas.DrawPath(builder.TakePath(), paint);
386
387 // Check that this empty picture can be created without crashing.
388 canvas.EndRecordingAsPicture();
389}

◆ TEST_P() [2/435]

impeller::testing::TEST_P ( AiksTest  ,
BlendModePlusAlphaColorFilterWideGamut   
)

Definition at line 157 of file aiks_blend_unittests.cc.

157 {
158 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
159 PixelFormat::kB10G10R10A10XR);
160 auto texture = CreateTextureForFixture("airplane.jpg",
161 /*enable_mipmapping=*/true);
162
163 Canvas canvas;
164 canvas.Scale(GetContentScale());
165 canvas.DrawPaint({.color = Color(0.1, 0.2, 0.1, 1.0)});
166 canvas.SaveLayer({
167 .color_filter =
168 ColorFilter::MakeBlend(BlendMode::kPlus, Color(Vector4{1, 0, 0, 1})),
169 });
170 Paint paint;
171 paint.color = Color::Red();
172 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
173 paint.color = Color::White();
174 canvas.DrawImageRect(
175 std::make_shared<Image>(texture), Rect::MakeSize(texture->GetSize()),
176 Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100), paint);
177 canvas.Restore();
178 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
179}
void DrawImageRect(const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
Definition canvas.cc:764
virtual void SaveLayer(const Paint &paint, std::optional< Rect > bounds=std::nullopt, const std::shared_ptr< ImageFilter > &backdrop_filter=nullptr, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, uint32_t total_content_depth=kMaxDepth)
Definition canvas.cc:839
virtual bool Restore()
Definition canvas.cc:257

◆ TEST_P() [3/435]

impeller::testing::TEST_P ( AiksTest  ,
BlendModePlusAlphaWideGamut   
)

Definition at line 134 of file aiks_blend_unittests.cc.

134 {
135 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
136 PixelFormat::kB10G10R10A10XR);
137 auto texture = CreateTextureForFixture("airplane.jpg",
138 /*enable_mipmapping=*/true);
139
140 Canvas canvas;
141 canvas.Scale(GetContentScale());
142 canvas.DrawPaint({.color = Color(0.9, 1.0, 0.9, 1.0)});
143 canvas.SaveLayer({});
144 Paint paint;
145 paint.blend_mode = BlendMode::kPlus;
146 paint.color = Color::Red();
147 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
148 paint.color = Color::White();
149 canvas.DrawImageRect(
150 std::make_shared<Image>(texture), Rect::MakeSize(texture->GetSize()),
151 Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100), paint);
152 canvas.Restore();
153 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
154}

◆ TEST_P() [4/435]

impeller::testing::TEST_P ( AiksTest  ,
BlendModeShouldCoverWholeScreen   
)

Definition at line 43 of file aiks_blend_unittests.cc.

43 {
44 Canvas canvas;
46
47 paint.color = Color::Red();
48 canvas.DrawPaint(paint);
49
50 paint.blend_mode = BlendMode::kSourceOver;
51 canvas.SaveLayer(paint);
52
53 paint.color = Color::White();
54 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
55
56 paint.blend_mode = BlendMode::kSource;
57 canvas.SaveLayer(paint);
58
59 paint.color = Color::Blue();
60 canvas.DrawRect(Rect::MakeXYWH(200, 200, 200, 200), paint);
61
62 canvas.Restore();
63 canvas.Restore();
64
65 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
66}

◆ TEST_P() [5/435]

impeller::testing::TEST_P ( AiksTest  ,
BlurHasNoEdge   
)

Definition at line 201 of file aiks_blur_unittests.cc.

201 {
202 Canvas canvas;
203 canvas.Scale(GetContentScale());
204 canvas.DrawPaint({});
205 Paint blur = {
206 .color = Color::Green(),
207 .mask_blur_descriptor =
209 .style = FilterContents::BlurStyle::kNormal,
210 .sigma = Sigma(47.6),
211 },
212 };
213 canvas.DrawRect(Rect::MakeXYWH(300, 300, 200, 200), blur);
214 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
215}

◆ TEST_P() [6/435]

impeller::testing::TEST_P ( AiksTest  ,
BlurredRectangleWithShader   
)

Definition at line 217 of file aiks_blur_unittests.cc.

217 {
218 Canvas canvas;
219 canvas.Scale(GetContentScale());
220
221 auto paint_lines = [&canvas](Scalar dx, Scalar dy, Paint paint) {
222 auto draw_line = [&canvas, &paint](Point a, Point b) {
224 };
225 paint.stroke_width = 5;
226 paint.style = Paint::Style::kStroke;
227 draw_line(Point(dx + 100, dy + 100), Point(dx + 200, dy + 200));
228 draw_line(Point(dx + 100, dy + 200), Point(dx + 200, dy + 100));
229 draw_line(Point(dx + 150, dy + 100), Point(dx + 200, dy + 150));
230 draw_line(Point(dx + 100, dy + 150), Point(dx + 150, dy + 200));
231 };
232
233 AiksContext renderer(GetContext(), nullptr);
234 Canvas recorder_canvas;
235 for (int x = 0; x < 5; ++x) {
236 for (int y = 0; y < 5; ++y) {
237 Rect rect = Rect::MakeXYWH(x * 20, y * 20, 20, 20);
238 Paint paint{.color =
239 ((x + y) & 1) == 0 ? Color::Yellow() : Color::Blue()};
240 recorder_canvas.DrawRect(rect, paint);
241 }
242 }
243 Picture picture = recorder_canvas.EndRecordingAsPicture();
244 std::shared_ptr<Texture> texture =
245 picture.ToImage(renderer, ISize{100, 100})->GetTexture();
246
247 ColorSource image_source = ColorSource::MakeImage(
248 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
249 std::shared_ptr<ImageFilter> blur_filter = ImageFilter::MakeBlur(
250 Sigma(5), Sigma(5), FilterContents::BlurStyle::kNormal,
251 Entity::TileMode::kDecal);
252 canvas.DrawRect(Rect::MakeLTRB(0, 0, 300, 600),
253 Paint{.color = Color::DarkGreen()});
254 canvas.DrawRect(Rect::MakeLTRB(100, 100, 200, 200),
255 Paint{.color_source = image_source});
256 canvas.DrawRect(Rect::MakeLTRB(300, 0, 600, 600),
257 Paint{.color = Color::Red()});
258 canvas.DrawRect(
259 Rect::MakeLTRB(400, 100, 500, 200),
260 Paint{.color_source = image_source, .image_filter = blur_filter});
261 paint_lines(0, 300, Paint{.color_source = image_source});
262 paint_lines(300, 300,
263 Paint{.color_source = image_source, .image_filter = blur_filter});
264 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
265}
static void draw_line(SkCanvas *canvas, SkImage *, const SkRect &r, sk_sp< SkImageFilter > imf)

◆ TEST_P() [7/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawAnOpenPath   
)

Definition at line 136 of file aiks_path_unittests.cc.

136 {
137 Canvas canvas;
138
139 // Starting at (50, 50), draw lines from:
140 // 1. (50, height)
141 // 2. (width, height)
142 // 3. (width, 50)
143 PathBuilder builder;
144 builder.MoveTo({50, 50});
145 builder.LineTo({50, 100});
146 builder.LineTo({100, 100});
147 builder.LineTo({100, 50});
148
149 Paint paint;
150 paint.color = Color::Red();
151 paint.style = Paint::Style::kStroke;
152 paint.stroke_width = 10;
153
154 canvas.DrawPath(builder.TakePath(), paint);
155
156 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
157}

◆ TEST_P() [8/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawAnOpenPathThatIsntARect   
)

Definition at line 159 of file aiks_path_unittests.cc.

159 {
160 Canvas canvas;
161
162 // Draw a stroked path that is explicitly closed to verify
163 // It doesn't become a rectangle.
164 PathBuilder builder;
165 builder.MoveTo({50, 50});
166 builder.LineTo({520, 120});
167 builder.LineTo({300, 310});
168 builder.LineTo({100, 50});
169 builder.Close();
170
171 Paint paint;
172 paint.color = Color::Red();
173 paint.style = Paint::Style::kStroke;
174 paint.stroke_width = 10;
175
176 canvas.DrawPath(builder.TakePath(), paint);
177
178 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
179}

◆ TEST_P() [9/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawMultiContourConvexPath   
)

Definition at line 345 of file aiks_path_unittests.cc.

345 {
346 PathBuilder builder = {};
347 for (auto i = 0; i < 10; i++) {
348 if (i % 2 == 0) {
349 builder.AddCircle(Point(100 + 50 * i, 100 + 50 * i), 100);
350 } else {
351 builder.MoveTo({100.f + 50.f * i - 100, 100.f + 50.f * i});
352 builder.LineTo({100.f + 50.f * i, 100.f + 50.f * i - 100});
353 builder.LineTo({100.f + 50.f * i - 100, 100.f + 50.f * i - 100});
354 builder.Close();
355 }
356 }
357 builder.SetConvexity(Convexity::kConvex);
358
359 Canvas canvas;
360 canvas.DrawPath(builder.TakePath(), {.color = Color::Red().WithAlpha(0.4)});
361
362 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
363}

◆ TEST_P() [10/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawPaint   
)

Definition at line 926 of file aiks_unittests.cc.

926 {
927 Canvas canvas;
928 canvas.Scale(Vector2(0.2, 0.2));
929 canvas.DrawPaint({.color = Color::MediumTurquoise()});
930 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
931}

◆ TEST_P() [11/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawPaintMultipleTimes   
)

Definition at line 933 of file aiks_unittests.cc.

933 {
934 Canvas canvas;
935 canvas.Scale(Vector2(0.2, 0.2));
936 canvas.DrawPaint({.color = Color::MediumTurquoise()});
937 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5)});
938 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
939}

◆ TEST_P() [12/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawPaintMultipleTimesInteractive   
)

Definition at line 524 of file aiks_blend_unittests.cc.

524 {
525 auto modes = GetBlendModeSelection();
526
527 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
528 static Color background = Color::MediumTurquoise();
529 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
530 static int current_blend_index = 3;
531
532 if (AiksTest::ImGuiBegin("Controls", nullptr,
533 ImGuiWindowFlags_AlwaysAutoResize)) {
534 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
535 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
536 ImGui::ListBox("Blend mode", &current_blend_index,
537 modes.blend_mode_names.data(),
538 modes.blend_mode_names.size());
539 ImGui::End();
540 }
541
542 Canvas canvas;
543 canvas.Scale(Vector2(0.2, 0.2));
544 canvas.DrawPaint({.color = background});
545 canvas.DrawPaint(
546 {.color = foreground,
547 .blend_mode = static_cast<BlendMode>(current_blend_index)});
548 return canvas.EndRecordingAsPicture();
549 };
550 ASSERT_TRUE(OpenPlaygroundHere(callback));
551}
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static BlendModeSelection GetBlendModeSelection()

◆ TEST_P() [13/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawPaintWithAdvancedBlend   
)

Definition at line 68 of file aiks_blend_unittests.cc.

68 {
69 Canvas canvas;
70 canvas.Scale(Vector2(0.2, 0.2));
71 canvas.DrawPaint({.color = Color::MediumTurquoise()});
72 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5),
73 .blend_mode = BlendMode::kHue});
74 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
75}

◆ TEST_P() [14/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawPerspectiveTransformWithClips   
)

Definition at line 3009 of file aiks_unittests.cc.

3009 {
3010 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
3011 int time = 0;
3012 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3013 Canvas canvas;
3014
3015 canvas.Save();
3016 {
3017 canvas.Translate({300, 300});
3018
3019 // 1. Draw/restore a clip before drawing the image, which will get drawn
3020 // to the depth buffer behind the image.
3021 canvas.Save();
3022 {
3023 canvas.DrawPaint({.color = Color::Green()});
3024 canvas.ClipRect(Rect::MakeLTRB(-180, -180, 180, 180),
3025 Entity::ClipOperation::kDifference);
3026 canvas.DrawPaint({.color = Color::Black()});
3027 }
3028 canvas.Restore(); // Restore rectangle difference clip.
3029
3030 canvas.Save();
3031 {
3032 // 2. Draw an oval clip that applies to the image, which will get drawn
3033 // in front of the image on the depth buffer.
3034 canvas.ClipOval(Rect::MakeLTRB(-200, -200, 200, 200));
3035
3036 // 3. Draw the rotating image with a perspective transform.
3037 canvas.Transform(
3038 Matrix(1.0, 0.0, 0.0, 0.0, //
3039 0.0, 1.0, 0.0, 0.0, //
3040 0.0, 0.0, 1.0, 0.003, //
3041 0.0, 0.0, 0.0, 1.0) * //
3042 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}}));
3043 auto image =
3044 std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
3045 canvas.DrawImage(image, -Point(image->GetSize()) / 2, {});
3046 }
3047 canvas.Restore(); // Restore oval intersect clip.
3048
3049 // 4. Draw a semi-translucent blue circle atop all previous draws.
3050 canvas.DrawCircle({}, 230, {.color = Color::Blue().WithAlpha(0.4)});
3051 }
3052 canvas.Restore(); // Restore translation.
3053
3054 return canvas.EndRecordingAsPicture();
3055 };
3056 ASSERT_TRUE(OpenPlaygroundHere(callback));
3057}
void Transform(const Matrix &transform)
Definition canvas.cc:292
void DrawImage(const std::shared_ptr< Image > &image, Point offset, const Paint &paint, SamplerDescriptor sampler={})
Definition canvas.cc:750
virtual void Save(uint32_t total_content_depth=kMaxDepth)
Definition canvas.cc:184
void ClipOval(const Rect &bounds, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition canvas.cc:618

◆ TEST_P() [15/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawPoints   
)

Definition at line 2351 of file aiks_unittests.cc.

2351 {
2352 std::vector<Point> points = {
2353 {0, 0}, //
2354 {100, 100}, //
2355 {100, 0}, //
2356 {0, 100}, //
2357 {0, 0}, //
2358 {48, 48}, //
2359 {52, 52}, //
2360 };
2361 std::vector<PointStyle> caps = {
2362 PointStyle::kRound,
2363 PointStyle::kSquare,
2364 };
2365 Paint paint;
2366 paint.color = Color::Yellow().WithAlpha(0.5);
2367
2368 Paint background;
2369 background.color = Color::Black();
2370
2371 Canvas canvas;
2372 canvas.DrawPaint(background);
2373 canvas.Translate({200, 200});
2374 canvas.DrawPoints(points, 10, paint, PointStyle::kRound);
2375 canvas.Translate({150, 0});
2376 canvas.DrawPoints(points, 10, paint, PointStyle::kSquare);
2377
2378 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2379}

◆ TEST_P() [16/435]

impeller::testing::TEST_P ( AiksTest  ,
CanDrawPointsWithTextureMap   
)

Definition at line 2445 of file aiks_unittests.cc.

2445 {
2446 auto texture = CreateTextureForFixture("table_mountain_nx.png",
2447 /*enable_mipmapping=*/true);
2448
2449 std::vector<Point> points = {
2450 {0, 0}, //
2451 {100, 100}, //
2452 {100, 0}, //
2453 {0, 100}, //
2454 {0, 0}, //
2455 {48, 48}, //
2456 {52, 52}, //
2457 };
2458 std::vector<PointStyle> caps = {
2459 PointStyle::kRound,
2460 PointStyle::kSquare,
2461 };
2462 Paint paint;
2463 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
2464 Entity::TileMode::kClamp, {}, {});
2465
2466 Canvas canvas;
2467 canvas.Translate({200, 200});
2468 canvas.DrawPoints(points, 100, paint, PointStyle::kRound);
2469 canvas.Translate({150, 0});
2470 canvas.DrawPoints(points, 100, paint, PointStyle::kSquare);
2471
2472 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2473}

◆ TEST_P() [17/435]

impeller::testing::TEST_P ( AiksTest  ,
CanEmptyPictureConvertToImage   
)

Definition at line 480 of file aiks_unittests.cc.

480 {
481 Canvas recorder_canvas;
482
483 Canvas canvas;
484 AiksContext renderer(GetContext(), nullptr);
485 Paint paint;
486 paint.color = Color::BlackTransparent();
487 canvas.DrawPaint(paint);
488 Picture picture = recorder_canvas.EndRecordingAsPicture();
489 auto image = picture.ToImage(renderer, ISize{1000, 1000});
490 if (image) {
491 canvas.DrawImage(image, Point(), Paint());
492 paint.color = Color{0.1, 0.1, 0.1, 0.2};
493 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
494 }
495
496 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
497}

◆ TEST_P() [18/435]

impeller::testing::TEST_P ( AiksTest  ,
CanPerformFullScreenMSAA   
)

Definition at line 564 of file aiks_unittests.cc.

564 {
565 Canvas canvas;
566
567 Paint red;
568 red.color = Color::Red();
569
570 canvas.DrawCircle({250, 250}, 125, red);
571
572 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
573}

◆ TEST_P() [19/435]

impeller::testing::TEST_P ( AiksTest  ,
CanPerformSaveLayerWithBounds   
)

Definition at line 587 of file aiks_unittests.cc.

587 {
588 Canvas canvas;
589
590 Paint red;
591 red.color = Color::Red();
592
593 Paint green;
594 green.color = Color::Green();
595
596 Paint blue;
597 blue.color = Color::Blue();
598
599 Paint save;
600 save.color = Color::Black();
601
602 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 50, 50));
603
604 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
605 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
606 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
607
608 canvas.Restore();
609
610 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
611}

◆ TEST_P() [20/435]

impeller::testing::TEST_P ( AiksTest  ,
CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated   
)

Definition at line 613 of file aiks_unittests.cc.

614 {
615 Canvas canvas;
616
617 Paint red;
618 red.color = Color::Red();
619
620 Paint green;
621 green.color = Color::Green();
622
623 Paint blue;
624 blue.color = Color::Blue();
625
626 Paint save;
627 save.color = Color::Black().WithAlpha(0.5);
628
629 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 100000, 100000));
630
631 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
632 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
633 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
634
635 canvas.Restore();
636
637 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
638}

◆ TEST_P() [21/435]

impeller::testing::TEST_P ( AiksTest  ,
CanPerformSkew   
)

Definition at line 575 of file aiks_unittests.cc.

575 {
576 Canvas canvas;
577
578 Paint red;
579 red.color = Color::Red();
580
581 canvas.Skew(2, 5);
582 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
583
584 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
585}
void Skew(Scalar sx, Scalar sy)
Definition canvas.cc:321

◆ TEST_P() [22/435]

impeller::testing::TEST_P ( AiksTest  ,
CanPictureConvertToImage   
)

Definition at line 454 of file aiks_unittests.cc.

454 {
455 Canvas recorder_canvas;
456 Paint paint;
457 paint.color = Color{0.9568, 0.2627, 0.2118, 1.0};
458 recorder_canvas.DrawRect(Rect::MakeXYWH(100.0, 100.0, 600, 600), paint);
459 paint.color = Color{0.1294, 0.5882, 0.9529, 1.0};
460 recorder_canvas.DrawRect(Rect::MakeXYWH(200.0, 200.0, 600, 600), paint);
461
462 Canvas canvas;
463 AiksContext renderer(GetContext(), nullptr);
464 paint.color = Color::BlackTransparent();
465 canvas.DrawPaint(paint);
466 Picture picture = recorder_canvas.EndRecordingAsPicture();
467 auto image = picture.ToImage(renderer, ISize{1000, 1000});
468 if (image) {
469 canvas.DrawImage(image, Point(), Paint());
470 paint.color = Color{0.1, 0.1, 0.1, 0.2};
471 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
472 }
473
474 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
475}

◆ TEST_P() [23/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderAdvancedBlendColorFilterWithSaveLayer   
)

Definition at line 21 of file aiks_blend_unittests.cc.

21 {
22 Canvas canvas;
23
24 Rect layer_rect = Rect::MakeXYWH(0, 0, 500, 500);
25 canvas.ClipRect(layer_rect);
26
27 canvas.SaveLayer(
28 {
29 .color_filter = ColorFilter::MakeBlend(BlendMode::kDifference,
30 Color(0, 1, 0, 0.5)),
31 },
32 layer_rect);
33
35 canvas.DrawPaint({.color = Color::Black()});
36 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300),
37 {.color = Color::White()});
38 canvas.Restore();
39
40 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
41}

◆ TEST_P() [24/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderBackdropBlur   
)

Definition at line 102 of file aiks_blur_unittests.cc.

102 {
103 Canvas canvas;
104 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
105 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
106 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
107 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
108 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
109 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
110 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
111 FilterContents::BlurStyle::kNormal,
112 Entity::TileMode::kClamp));
113 canvas.Restore();
114
115 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
116}

◆ TEST_P() [25/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderBackdropBlurHugeSigma   
)

Definition at line 118 of file aiks_blur_unittests.cc.

118 {
119 Canvas canvas;
120 canvas.DrawCircle({400, 400}, 300, {.color = Color::Green()});
121 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
122 ImageFilter::MakeBlur(Sigma(999999), Sigma(999999),
123 FilterContents::BlurStyle::kNormal,
124 Entity::TileMode::kClamp));
125 canvas.Restore();
126
127 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
128}

◆ TEST_P() [26/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderBackdropBlurInteractive   
)

Definition at line 78 of file aiks_blur_unittests.cc.

78 {
79 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
80 static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
81 static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
82 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
83
84 Canvas canvas;
85 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
86 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
87 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
88 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
89 canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), {20, 20});
90 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
91 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
92 FilterContents::BlurStyle::kNormal,
93 Entity::TileMode::kClamp));
94 canvas.Restore();
95
96 return canvas.EndRecordingAsPicture();
97 };
98
99 ASSERT_TRUE(OpenPlaygroundHere(callback));
100}
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition widgets.cc:50

◆ TEST_P() [27/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderClippedBackdropFilter   
)

Definition at line 3059 of file aiks_unittests.cc.

3059 {
3060 Canvas canvas;
3061 Paint paint;
3062
3063 canvas.Scale(GetContentScale());
3064
3065 // Draw something interesting in the background.
3066 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
3067 Color{0.1294, 0.5882, 0.9529, 1.0}};
3068 std::vector<Scalar> stops = {
3069 0.0,
3070 1.0,
3071 };
3072 paint.color_source = ColorSource::MakeLinearGradient(
3073 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
3074 Entity::TileMode::kRepeat, {});
3075 canvas.DrawPaint(paint);
3076
3077 Rect clip_rect = Rect::MakeLTRB(50, 50, 400, 300);
3078
3079 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
3080 // the same.
3081 canvas.ClipRRect(clip_rect, Size(100, 100),
3082 Entity::ClipOperation::kIntersect);
3083 canvas.SaveLayer({}, clip_rect,
3084 ImageFilter::MakeFromColorFilter(*ColorFilter::MakeBlend(
3085 BlendMode::kExclusion, Color::Red())));
3086 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3087}

◆ TEST_P() [28/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderClippedBlur   
)

Definition at line 130 of file aiks_blur_unittests.cc.

130 {
131 Canvas canvas;
132 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
133 canvas.DrawCircle(
134 {400, 400}, 200,
135 {
136 .color = Color::Green(),
137 .image_filter = ImageFilter::MakeBlur(
138 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
139 Entity::TileMode::kDecal),
140 });
141 canvas.Restore();
142
143 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
144}

◆ TEST_P() [29/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderClippedLayers   
)

Definition at line 1514 of file aiks_unittests.cc.

1514 {
1515 Canvas canvas;
1516
1517 canvas.DrawPaint({.color = Color::White()});
1518
1519 // Draw a green circle on the screen.
1520 {
1521 // Increase the clip depth for the savelayer to contend with.
1522 canvas.ClipPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath());
1523
1524 canvas.SaveLayer({}, Rect::MakeXYWH(50, 50, 100, 100));
1525
1526 // Fill the layer with white.
1527 canvas.DrawRect(Rect::MakeSize(Size{400, 400}), {.color = Color::White()});
1528 // Fill the layer with green, but do so with a color blend that can't be
1529 // collapsed into the parent pass.
1530 // TODO(jonahwilliams): this blend mode was changed from color burn to
1531 // hardlight to work around https://github.com/flutter/flutter/issues/136554
1532 // .
1533 canvas.DrawRect(
1534 Rect::MakeSize(Size{400, 400}),
1535 {.color = Color::Green(), .blend_mode = BlendMode::kHardLight});
1536 }
1537
1538 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1539}

◆ TEST_P() [30/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderClippedRuntimeEffects   
)

Definition at line 2289 of file aiks_unittests.cc.

2289 {
2290 auto runtime_stages =
2291 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2292
2293 auto runtime_stage =
2294 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2295 ASSERT_TRUE(runtime_stage);
2296 ASSERT_TRUE(runtime_stage->IsDirty());
2297
2298 struct FragUniforms {
2299 Vector2 iResolution;
2300 Scalar iTime;
2301 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
2302 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2303 uniform_data->resize(sizeof(FragUniforms));
2304 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2305
2306 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2307
2308 Paint paint;
2309 paint.color_source = ColorSource::MakeRuntimeEffect(
2310 runtime_stage, uniform_data, texture_inputs);
2311
2312 Canvas canvas;
2313 canvas.Save();
2314 canvas.ClipRRect(Rect::MakeXYWH(0, 0, 400, 400), {10.0, 10.0},
2315 Entity::ClipOperation::kIntersect);
2316 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), paint);
2317 canvas.Restore();
2318
2319 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2320}
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
Definition playground.h:35

◆ TEST_P() [31/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderClips   
)

Definition at line 391 of file aiks_path_unittests.cc.

391 {
392 Canvas canvas;
393 Paint paint;
394 paint.color = Color::Fuchsia();
395 canvas.ClipPath(
396 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 500, 500)).TakePath());
397 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
398 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
399}

◆ TEST_P() [32/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderColoredRect   
)

Definition at line 77 of file aiks_unittests.cc.

77 {
78 Canvas canvas;
80 paint.color = Color::Blue();
81 canvas.DrawPath(PathBuilder{}
82 .AddRect(Rect::MakeXYWH(100.0, 100.0, 100.0, 100.0))
83 .TakePath(),
84 paint);
85 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
86}

◆ TEST_P() [33/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderColorFilterWithInvertColors   
)

Definition at line 110 of file aiks_unittests.cc.

110 {
111 Canvas canvas;
112 Paint paint;
113 paint.color = Color::Red();
114 paint.color_filter =
115 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
116 paint.invert_colors = true;
117
118 canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint);
119 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
120}

◆ TEST_P() [34/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderColorFilterWithInvertColorsDrawPaint   
)

Definition at line 122 of file aiks_unittests.cc.

122 {
123 Canvas canvas;
124 Paint paint;
125 paint.color = Color::Red();
126 paint.color_filter =
127 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
128 paint.invert_colors = true;
129
130 canvas.DrawPaint(paint);
131 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
132}

◆ TEST_P() [35/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderConicalGradient   
)

Definition at line 562 of file aiks_gradient_unittests.cc.

562 {
563 Scalar size = 256;
564 Canvas canvas;
565 Paint paint;
566 paint.color = Color::White();
567 canvas.DrawRect(Rect::MakeXYWH(0, 0, size * 3, size * 3), paint);
568 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
569 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
570 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
571 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
572 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
573 std::array<std::tuple<Point, float, Point, float>, 8> array{
574 std::make_tuple(Point{size / 2.f, size / 2.f}, 0.f,
575 Point{size / 2.f, size / 2.f}, size / 2.f),
576 std::make_tuple(Point{size / 2.f, size / 2.f}, size / 4.f,
577 Point{size / 2.f, size / 2.f}, size / 2.f),
578 std::make_tuple(Point{size / 4.f, size / 4.f}, 0.f,
579 Point{size / 2.f, size / 2.f}, size / 2.f),
580 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 2.f,
581 Point{size / 2.f, size / 2.f}, 0),
582 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 4.f,
583 Point{size / 2.f, size / 2.f}, size / 2.f),
584 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 16.f,
585 Point{size / 2.f, size / 2.f}, size / 8.f),
586 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 8.f,
587 Point{size / 2.f, size / 2.f}, size / 16.f),
588 std::make_tuple(Point{size / 8.f, size / 8.f}, size / 8.f,
589 Point{size / 2.f, size / 2.f}, size / 8.f),
590 };
591 for (int i = 0; i < 8; i++) {
592 canvas.Save();
593 canvas.Translate({(i % 3) * size, i / 3 * size, 0});
594 paint.color_source = ColorSource::MakeConicalGradient(
595 std::get<0>(array[i]), std::get<1>(array[i]), colors, stops,
596 std::get<2>(array[i]), std::get<3>(array[i]), Entity::TileMode::kClamp,
597 {});
598 canvas.DrawRect(Rect::MakeXYWH(0, 0, size, size), paint);
599 canvas.Restore();
600 }
601 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
602}
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259

◆ TEST_P() [36/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderConicalGradientWithDitheringDisabled   
)

Definition at line 187 of file aiks_gradient_unittests.cc.

187 {
189}
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test, bool use_dithering)

◆ TEST_P() [37/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderConicalGradientWithDitheringEnabled   
)

Definition at line 191 of file aiks_gradient_unittests.cc.

191 {
193}

◆ TEST_P() [38/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderCurvedStrokes   
)

Definition at line 56 of file aiks_path_unittests.cc.

56 {
57 Canvas canvas;
59 paint.color = Color::Red();
60 paint.stroke_width = 25.0;
61 paint.style = Paint::Style::kStroke;
62 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
63 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
64}

◆ TEST_P() [39/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderDestructiveSaveLayer   
)

Definition at line 2274 of file aiks_unittests.cc.

2274 {
2275 Canvas canvas;
2276
2277 canvas.DrawPaint({.color = Color::Red()});
2278 // Draw an empty savelayer with a destructive blend mode, which will replace
2279 // the entire red screen with fully transparent black, except for the green
2280 // circle drawn within the layer.
2281 canvas.SaveLayer({.blend_mode = BlendMode::kSource});
2282 canvas.DrawCircle({300, 300}, 100, {.color = Color::Green()});
2283 canvas.Restore();
2284
2285 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2286}

◆ TEST_P() [40/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderDifferenceClips   
)

Definition at line 331 of file aiks_unittests.cc.

331 {
332 Paint paint;
333 Canvas canvas;
334 canvas.Translate({400, 400});
335
336 // Limit drawing to face circle with a clip.
337 canvas.ClipPath(PathBuilder{}.AddCircle(Point(), 200).TakePath());
338 canvas.Save();
339
340 // Cut away eyes/mouth using difference clips.
341 canvas.ClipPath(PathBuilder{}.AddCircle({-100, -50}, 30).TakePath(),
342 Entity::ClipOperation::kDifference);
343 canvas.ClipPath(PathBuilder{}.AddCircle({100, -50}, 30).TakePath(),
344 Entity::ClipOperation::kDifference);
345 canvas.ClipPath(PathBuilder{}
346 .AddQuadraticCurve({-100, 50}, {0, 150}, {100, 50})
347 .TakePath(),
348 Entity::ClipOperation::kDifference);
349
350 // Draw a huge yellow rectangle to prove the clipping works.
351 paint.color = Color::Yellow();
352 canvas.DrawRect(Rect::MakeXYWH(-1000, -1000, 2000, 2000), paint);
353
354 // Remove the difference clips and draw hair that partially covers the eyes.
355 canvas.Restore();
356 paint.color = Color::Maroon();
357 canvas.DrawPath(PathBuilder{}
358 .MoveTo({200, -200})
359 .HorizontalLineTo(-200)
360 .VerticalLineTo(-40)
361 .CubicCurveTo({0, -40}, {0, -80}, {200, -80})
362 .TakePath(),
363 paint);
364
365 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
366}

◆ TEST_P() [41/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderDifferencePaths   
)

Definition at line 107 of file aiks_path_unittests.cc.

107 {
108 Canvas canvas;
109
110 Paint paint;
111 paint.color = Color::Red();
112
113 PathBuilder builder;
114
116 radii.top_left = {50, 25};
117 radii.top_right = {25, 50};
118 radii.bottom_right = {50, 25};
119 radii.bottom_left = {25, 50};
120
121 builder.AddRoundedRect(Rect::MakeXYWH(100, 100, 200, 200), radii);
122 builder.AddCircle({200, 200}, 50);
123 auto path = builder.TakePath(FillType::kOdd);
124
125 canvas.DrawImage(
126 std::make_shared<Image>(CreateTextureForFixture("boston.jpg")), {10, 10},
127 Paint{});
128 canvas.DrawPath(path, paint);
129
130 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
131}

◆ TEST_P() [42/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderDifferentShapesWithSameColorSource   
)

Definition at line 427 of file aiks_unittests.cc.

427 {
428 Canvas canvas;
429 Paint paint;
430
431 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
432 Color{0.1294, 0.5882, 0.9529, 1.0}};
433 std::vector<Scalar> stops = {
434 0.0,
435 1.0,
436 };
437
438 paint.color_source = ColorSource::MakeLinearGradient(
439 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
440 Entity::TileMode::kRepeat, {});
441
442 canvas.Save();
443 canvas.Translate({100, 100, 0});
444 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), paint);
445 canvas.Restore();
446
447 canvas.Save();
448 canvas.Translate({100, 400, 0});
449 canvas.DrawCircle({100, 100}, 100, paint);
450 canvas.Restore();
451 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
452}

◆ TEST_P() [43/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderEmojiTextFrame   
)

Definition at line 818 of file aiks_unittests.cc.

818 {
819 Canvas canvas;
820 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
821
822 ASSERT_TRUE(RenderTextInCanvasSkia(
823 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
824 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
825}

◆ TEST_P() [44/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderEmojiTextFrameWithAlpha   
)

Definition at line 840 of file aiks_unittests.cc.

840 {
841 Canvas canvas;
842 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
843
844 ASSERT_TRUE(RenderTextInCanvasSkia(
845 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
846 {.color = Color::Black().WithAlpha(0.5)}));
847 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
848}

◆ TEST_P() [45/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderEmojiTextFrameWithBlur   
)

Definition at line 827 of file aiks_unittests.cc.

827 {
828 Canvas canvas;
829 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
830
831 ASSERT_TRUE(RenderTextInCanvasSkia(
832 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
833 TextRenderOptions{.color = Color::Blue(),
834 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
835 .style = FilterContents::BlurStyle::kNormal,
836 .sigma = Sigma(4)}}));
837 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
838}

◆ TEST_P() [46/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderForegroundAdvancedBlendWithMaskBlur   
)

Definition at line 57 of file aiks_blur_unittests.cc.

57 {
58 // This case triggers the ForegroundAdvancedBlend path. The color filter
59 // should apply to the color only, and respect the alpha mask.
60 Canvas canvas;
61 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
62 canvas.DrawCircle({400, 400}, 200,
63 {
64 .color = Color::Grey(),
65 .color_filter = ColorFilter::MakeBlend(
66 BlendMode::kColor, Color::Green()),
67 .mask_blur_descriptor =
69 .style = FilterContents::BlurStyle::kNormal,
70 .sigma = Radius(20),
71 },
72 });
73 canvas.Restore();
74
75 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
76}
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition sigma.h:48

◆ TEST_P() [47/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderForegroundBlendWithMaskBlur   
)

Definition at line 36 of file aiks_blur_unittests.cc.

36 {
37 // This case triggers the ForegroundPorterDuffBlend path. The color filter
38 // should apply to the color only, and respect the alpha mask.
39 Canvas canvas;
40 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
41 canvas.DrawCircle({400, 400}, 200,
42 {
43 .color = Color::White(),
44 .color_filter = ColorFilter::MakeBlend(
45 BlendMode::kSource, Color::Green()),
46 .mask_blur_descriptor =
48 .style = FilterContents::BlurStyle::kNormal,
49 .sigma = Radius(20),
50 },
51 });
52 canvas.Restore();
53
54 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
55}

◆ TEST_P() [48/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderGradientDecalWithBackground   
)

Definition at line 604 of file aiks_gradient_unittests.cc.

604 {
605 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
606 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
607 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
608 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
609 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
610
611 std::array<ColorSource, 3> color_sources = {
612 ColorSource::MakeLinearGradient({0, 0}, {100, 100}, colors, stops,
613 Entity::TileMode::kDecal, {}),
614 ColorSource::MakeRadialGradient({100, 100}, 100, colors, stops,
615 Entity::TileMode::kDecal, {}),
616 ColorSource::MakeSweepGradient({100, 100}, Degrees(45), Degrees(135),
617 colors, stops, Entity::TileMode::kDecal,
618 {}),
619 };
620
621 Canvas canvas;
622 Paint paint;
623 paint.color = Color::White();
624 canvas.DrawRect(Rect::MakeLTRB(0, 0, 605, 205), paint);
625 for (int i = 0; i < 3; i++) {
626 canvas.Save();
627 canvas.Translate({i * 200.0f, 0, 0});
628 paint.color_source = color_sources[i];
629 canvas.DrawRect(Rect::MakeLTRB(0, 0, 200, 200), paint);
630 canvas.Restore();
631 }
632 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
633}

◆ TEST_P() [49/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderGroupOpacity   
)

Definition at line 499 of file aiks_unittests.cc.

499 {
500 Canvas canvas;
501
502 Paint red;
503 red.color = Color::Red();
504 Paint green;
505 green.color = Color::Green().WithAlpha(0.5);
506 Paint blue;
507 blue.color = Color::Blue();
508
509 Paint alpha;
510 alpha.color = Color::Red().WithAlpha(0.5);
511
512 canvas.SaveLayer(alpha);
513
514 canvas.DrawRect(Rect::MakeXYWH(000, 000, 100, 100), red);
515 canvas.DrawRect(Rect::MakeXYWH(020, 020, 100, 100), green);
516 canvas.DrawRect(Rect::MakeXYWH(040, 040, 100, 100), blue);
517
518 canvas.Restore();
519
520 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
521}

◆ TEST_P() [50/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderImage   
)

Definition at line 88 of file aiks_unittests.cc.

88 {
89 Canvas canvas;
91 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
92 paint.color = Color::Red();
93 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
94 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
95}

◆ TEST_P() [51/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderImageRect   
)

Definition at line 223 of file aiks_unittests.cc.

223 {
224 Canvas canvas;
225 Paint paint;
226 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
227 Size image_half_size = Size(image->GetSize()) * 0.5;
228
229 // Render the bottom right quarter of the source image in a stretched rect.
230 auto source_rect = Rect::MakeSize(image_half_size);
231 source_rect = source_rect.Shift(Point(image_half_size));
232
233 canvas.DrawImageRect(image, source_rect, Rect::MakeXYWH(100, 100, 600, 600),
234 paint);
235 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
236}

◆ TEST_P() [52/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderInvertedImageWithColorFilter   
)

Definition at line 97 of file aiks_unittests.cc.

97 {
98 Canvas canvas;
100 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
101 paint.color = Color::Red();
102 paint.color_filter =
103 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
104 paint.invert_colors = true;
105
106 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
107 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
108}

◆ TEST_P() [53/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderItalicizedText   
)

Definition at line 801 of file aiks_unittests.cc.

801 {
802 Canvas canvas;
803 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
804
805 ASSERT_TRUE(RenderTextInCanvasSkia(
806 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
807 "HomemadeApple.ttf"));
808 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
809}

◆ TEST_P() [54/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientClamp   
)

Definition at line 45 of file aiks_gradient_unittests.cc.

45 {
46 CanRenderLinearGradient(this, Entity::TileMode::kClamp);
47}

◆ TEST_P() [55/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientDecal   
)

Definition at line 54 of file aiks_gradient_unittests.cc.

54 {
55 CanRenderLinearGradient(this, Entity::TileMode::kDecal);
56}

◆ TEST_P() [56/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientDecalWithColorFilter   
)

Definition at line 58 of file aiks_gradient_unittests.cc.

58 {
59 Canvas canvas;
60 canvas.Scale(GetContentScale());
62 canvas.Translate({100.0f, 0, 0});
63
64 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
65 Color{0.1294, 0.5882, 0.9529, 0.0}};
66 std::vector<Scalar> stops = {0.0, 1.0};
67
68 paint.color_source = ColorSource::MakeLinearGradient(
69 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
70 Entity::TileMode::kDecal, {});
71 // Overlay the gradient with 25% green. This should appear as the entire
72 // rectangle being drawn with 25% green, including the border area outside the
73 // decal gradient.
74 paint.color_filter = ColorFilter::MakeBlend(BlendMode::kSourceOver,
75 Color::Green().WithAlpha(0.25));
76
77 paint.color = Color(1.0, 1.0, 1.0, 1.0);
78 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
79 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
80}

◆ TEST_P() [57/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientManyColorsClamp   
)

Definition at line 257 of file aiks_gradient_unittests.cc.

257 {
258 CanRenderLinearGradientManyColors(this, Entity::TileMode::kClamp);
259}

◆ TEST_P() [58/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientManyColorsDecal   
)

Definition at line 266 of file aiks_gradient_unittests.cc.

266 {
267 CanRenderLinearGradientManyColors(this, Entity::TileMode::kDecal);
268}

◆ TEST_P() [59/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientManyColorsMirror   
)

Definition at line 263 of file aiks_gradient_unittests.cc.

263 {
264 CanRenderLinearGradientManyColors(this, Entity::TileMode::kMirror);
265}

◆ TEST_P() [60/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientManyColorsRepeat   
)

Definition at line 260 of file aiks_gradient_unittests.cc.

260 {
261 CanRenderLinearGradientManyColors(this, Entity::TileMode::kRepeat);
262}

◆ TEST_P() [61/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientManyColorsUnevenStops   
)

Definition at line 300 of file aiks_gradient_unittests.cc.

300 {
301 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
302 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
303 const Entity::TileMode tile_modes[] = {
304 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
305 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
306
307 static int selected_tile_mode = 0;
308 static Matrix matrix = {
309 1, 0, 0, 0, //
310 0, 1, 0, 0, //
311 0, 0, 1, 0, //
312 0, 0, 0, 1 //
313 };
314 if (AiksTest::ImGuiBegin("Controls", nullptr,
315 ImGuiWindowFlags_AlwaysAutoResize)) {
316 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
317 sizeof(tile_mode_names) / sizeof(char*));
318 std::string label = "##1";
319 for (int i = 0; i < 4; i++) {
320 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
321 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
322 label[2]++;
323 }
324 ImGui::End();
325 }
326
327 Canvas canvas;
328 Paint paint;
329 canvas.Translate({100.0, 100.0, 0});
330 auto tile_mode = tile_modes[selected_tile_mode];
331
332 std::vector<Color> colors = {
333 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
334 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
335 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
336 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
337 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
338 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
339 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
340 std::vector<Scalar> stops = {
341 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
342 };
343
344 paint.color_source = ColorSource::MakeLinearGradient(
345 {0, 0}, {200, 200}, std::move(colors), std::move(stops), tile_mode, {});
346
347 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
348 return canvas.EndRecordingAsPicture();
349 };
350 ASSERT_TRUE(OpenPlaygroundHere(callback));
351}

◆ TEST_P() [62/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientMaskBlur   
)

Definition at line 353 of file aiks_gradient_unittests.cc.

353 {
354 Canvas canvas;
355
356 Paint paint = {
357 .color = Color::White(),
358 .color_source = ColorSource::MakeLinearGradient(
359 {200, 200}, {400, 400},
360 {Color::Red(), Color::White(), Color::Red(), Color::White(),
361 Color::Red(), Color::White(), Color::Red(), Color::White(),
362 Color::Red(), Color::White(), Color::Red()},
363 {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0},
364 Entity::TileMode::kClamp, {}),
365 .mask_blur_descriptor =
366 Paint::MaskBlurDescriptor{
367 .style = FilterContents::BlurStyle::kNormal,
368 .sigma = Sigma(20),
369 },
370 };
371
372 canvas.DrawCircle({300, 300}, 200, paint);
373 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
374
375 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
376}

◆ TEST_P() [63/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientMirror   
)

Definition at line 51 of file aiks_gradient_unittests.cc.

51 {
52 CanRenderLinearGradient(this, Entity::TileMode::kMirror);
53}

◆ TEST_P() [64/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientRepeat   
)

Definition at line 48 of file aiks_gradient_unittests.cc.

48 {
49 CanRenderLinearGradient(this, Entity::TileMode::kRepeat);
50}

◆ TEST_P() [65/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientWayManyColorsClamp   
)

Definition at line 296 of file aiks_gradient_unittests.cc.

296 {
297 CanRenderLinearGradientWayManyColors(this, Entity::TileMode::kClamp);
298}

◆ TEST_P() [66/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientWithDitheringDisabled   
)

Definition at line 102 of file aiks_gradient_unittests.cc.

102 {
104}
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test, bool use_dithering)

◆ TEST_P() [67/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientWithDitheringEnabled   
)

Definition at line 106 of file aiks_gradient_unittests.cc.

106 {
108} // namespace

◆ TEST_P() [68/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderLinearGradientWithOverlappingStopsClamp   
)

Definition at line 217 of file aiks_gradient_unittests.cc.

217 {
218 CanRenderLinearGradientWithOverlappingStops(this, Entity::TileMode::kClamp);
219}

◆ TEST_P() [69/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderMaskBlurHugeSigma   
)

Definition at line 23 of file aiks_blur_unittests.cc.

23 {
24 Canvas canvas;
25 canvas.DrawCircle({400, 400}, 300,
26 {.color = Color::Green(),
27 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
28 .style = FilterContents::BlurStyle::kNormal,
29 .sigma = Sigma(99999),
30 }});
31 canvas.Restore();
32
33 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
34}

◆ TEST_P() [70/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderNestedClips   
)

Definition at line 318 of file aiks_unittests.cc.

318 {
319 Canvas canvas;
320 Paint paint;
321 paint.color = Color::Fuchsia();
322 canvas.Save();
323 canvas.ClipPath(PathBuilder{}.AddCircle({200, 400}, 300).TakePath());
324 canvas.Restore();
325 canvas.ClipPath(PathBuilder{}.AddCircle({600, 400}, 300).TakePath());
326 canvas.ClipPath(PathBuilder{}.AddCircle({400, 600}, 300).TakePath());
327 canvas.DrawRect(Rect::MakeXYWH(200, 200, 400, 400), paint);
328 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
329}

◆ TEST_P() [71/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderOffscreenCheckerboard   
)

Tests that the debug checkerboard displays for offscreen textures when enabled. Most of the complexity here is just to future proof by making pass collapsing hard.

Definition at line 2224 of file aiks_unittests.cc.

2224 {
2225 Canvas canvas;
2227
2228 canvas.DrawPaint({.color = Color::AntiqueWhite()});
2229 canvas.DrawCircle({400, 300}, 200,
2230 {.color = Color::CornflowerBlue().WithAlpha(0.75)});
2231
2232 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
2233 {
2234 canvas.DrawCircle({500, 400}, 200,
2235 {.color = Color::DarkBlue().WithAlpha(0.75)});
2236 canvas.DrawCircle({550, 450}, 200,
2237 {.color = Color::LightCoral().WithAlpha(0.75),
2238 .blend_mode = BlendMode::kLuminosity});
2239 }
2240 canvas.Restore();
2241
2242 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2243}
struct impeller::Canvas::DebugOptions debug_options

◆ TEST_P() [72/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderOverlappingMultiContourPath   
)

Definition at line 401 of file aiks_path_unittests.cc.

401 {
402 Canvas canvas;
403
404 Paint paint;
405 paint.color = Color::Red();
406
408 radii.top_left = {50, 50};
409 radii.top_right = {50, 50};
410 radii.bottom_right = {50, 50};
411 radii.bottom_left = {50, 50};
412
413 const Scalar kTriangleHeight = 100;
414 canvas.Translate(Vector2(200, 200));
415 // Form a path similar to the Material drop slider value indicator. Both
416 // shapes should render identically side-by-side.
417 {
418 auto path =
419 PathBuilder{}
420 .MoveTo({0, kTriangleHeight})
421 .LineTo({-kTriangleHeight / 2.0f, 0})
422 .LineTo({kTriangleHeight / 2.0f, 0})
423 .Close()
424 .AddRoundedRect(
425 Rect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
426 kTriangleHeight, kTriangleHeight),
427 radii)
428 .TakePath();
429
430 canvas.DrawPath(path, paint);
431 }
432 canvas.Translate(Vector2(100, 0));
433 {
434 auto path =
435 PathBuilder{}
436 .MoveTo({0, kTriangleHeight})
437 .LineTo({-kTriangleHeight / 2.0f, 0})
438 .LineTo({0, -10})
439 .LineTo({kTriangleHeight / 2.0f, 0})
440 .Close()
441 .AddRoundedRect(
442 Rect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
443 kTriangleHeight, kTriangleHeight),
444 radii)
445 .TakePath();
446
447 canvas.DrawPath(path, paint);
448 }
449
450 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
451}

◆ TEST_P() [73/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderRadialGradient   
)

Definition at line 378 of file aiks_gradient_unittests.cc.

378 {
379 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
380 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
381 const Entity::TileMode tile_modes[] = {
382 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
383 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
384
385 static int selected_tile_mode = 0;
386 static Matrix matrix = {
387 1, 0, 0, 0, //
388 0, 1, 0, 0, //
389 0, 0, 1, 0, //
390 0, 0, 0, 1 //
391 };
392 if (AiksTest::ImGuiBegin("Controls", nullptr,
393 ImGuiWindowFlags_AlwaysAutoResize)) {
394 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
395 sizeof(tile_mode_names) / sizeof(char*));
396 std::string label = "##1";
397 for (int i = 0; i < 4; i++) {
398 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
399 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
400 label[2]++;
401 }
402 ImGui::End();
403 }
404
405 Canvas canvas;
406 Paint paint;
407 canvas.Translate({100.0, 100.0, 0});
408 auto tile_mode = tile_modes[selected_tile_mode];
409
410 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
411 Color{0.1294, 0.5882, 0.9529, 1.0}};
412 std::vector<Scalar> stops = {0.0, 1.0};
413
414 paint.color_source = ColorSource::MakeRadialGradient(
415 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
416
417 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
418 return canvas.EndRecordingAsPicture();
419 };
420 ASSERT_TRUE(OpenPlaygroundHere(callback));
421}

◆ TEST_P() [74/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderRadialGradientManyColors   
)

Definition at line 423 of file aiks_gradient_unittests.cc.

423 {
424 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
425 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
426 const Entity::TileMode tile_modes[] = {
427 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
428 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
429
430 static int selected_tile_mode = 0;
431 static Matrix matrix = {
432 1, 0, 0, 0, //
433 0, 1, 0, 0, //
434 0, 0, 1, 0, //
435 0, 0, 0, 1 //
436 };
437 if (AiksTest::ImGuiBegin("Controls", nullptr,
438 ImGuiWindowFlags_AlwaysAutoResize)) {
439 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
440 sizeof(tile_mode_names) / sizeof(char*));
441 std::string label = "##1";
442 for (int i = 0; i < 4; i++) {
443 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
444 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
445 label[2]++;
446 }
447 ImGui::End();
448 }
449
450 Canvas canvas;
451 Paint paint;
452 canvas.Translate({100.0, 100.0, 0});
453 auto tile_mode = tile_modes[selected_tile_mode];
454
455 std::vector<Color> colors = {
456 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
457 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
458 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
459 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
460 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
461 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
462 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
463 std::vector<Scalar> stops = {
464 0.0,
465 (1.0 / 6.0) * 1,
466 (1.0 / 6.0) * 2,
467 (1.0 / 6.0) * 3,
468 (1.0 / 6.0) * 4,
469 (1.0 / 6.0) * 5,
470 1.0,
471 };
472
473 paint.color_source = ColorSource::MakeRadialGradient(
474 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
475
476 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
477 return canvas.EndRecordingAsPicture();
478 };
479 ASSERT_TRUE(OpenPlaygroundHere(callback));
480}

◆ TEST_P() [75/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderRadialGradientWithDitheringDisabled   
)

Definition at line 129 of file aiks_gradient_unittests.cc.

129 {
131}
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test, bool use_dithering)

◆ TEST_P() [76/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderRadialGradientWithDitheringEnabled   
)

Definition at line 133 of file aiks_gradient_unittests.cc.

133 {
135}

◆ TEST_P() [77/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderRoundedRectWithNonUniformRadii   
)

Definition at line 640 of file aiks_unittests.cc.

640 {
641 Canvas canvas;
642
643 Paint paint;
644 paint.color = Color::Red();
645
647 radii.top_left = {50, 25};
648 radii.top_right = {25, 50};
649 radii.bottom_right = {50, 25};
650 radii.bottom_left = {25, 50};
651
652 auto path = PathBuilder{}
653 .AddRoundedRect(Rect::MakeXYWH(100, 100, 500, 500), radii)
654 .TakePath();
655
656 canvas.DrawPath(path, paint);
657
658 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
659}

◆ TEST_P() [78/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSimpleClips   
)

Definition at line 238 of file aiks_unittests.cc.

238 {
239 Canvas canvas;
240 canvas.Scale(GetContentScale());
241 Paint paint;
242
243 paint.color = Color::White();
244 canvas.DrawPaint(paint);
245
246 auto draw = [&canvas](const Paint& paint, Scalar x, Scalar y) {
247 canvas.Save();
248 canvas.Translate({x, y});
249 {
250 canvas.Save();
251 canvas.ClipRect(Rect::MakeLTRB(50, 50, 150, 150));
252 canvas.DrawPaint(paint);
253 canvas.Restore();
254 }
255 {
256 canvas.Save();
257 canvas.ClipOval(Rect::MakeLTRB(200, 50, 300, 150));
258 canvas.DrawPaint(paint);
259 canvas.Restore();
260 }
261 {
262 canvas.Save();
263 canvas.ClipRRect(Rect::MakeLTRB(50, 200, 150, 300), {20, 20});
264 canvas.DrawPaint(paint);
265 canvas.Restore();
266 }
267 {
268 canvas.Save();
269 canvas.ClipRRect(Rect::MakeLTRB(200, 230, 300, 270), {20, 20});
270 canvas.DrawPaint(paint);
271 canvas.Restore();
272 }
273 {
274 canvas.Save();
275 canvas.ClipRRect(Rect::MakeLTRB(230, 200, 270, 300), {20, 20});
276 canvas.DrawPaint(paint);
277 canvas.Restore();
278 }
279 canvas.Restore();
280 };
281
282 paint.color = Color::Blue();
283 draw(paint, 0, 0);
284
285 std::vector<Color> gradient_colors = {
286 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
287 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
288 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
289 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
290 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
291 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
292 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
293 std::vector<Scalar> stops = {
294 0.0,
295 (1.0 / 6.0) * 1,
296 (1.0 / 6.0) * 2,
297 (1.0 / 6.0) * 3,
298 (1.0 / 6.0) * 4,
299 (1.0 / 6.0) * 5,
300 1.0,
301 };
302 auto texture = CreateTextureForFixture("airplane.jpg",
303 /*enable_mipmapping=*/true);
304
305 paint.color_source = ColorSource::MakeRadialGradient(
306 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
307 Entity::TileMode::kMirror, {});
308 draw(paint, 0, 300);
309
310 paint.color_source = ColorSource::MakeImage(
311 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
312 Matrix::MakeTranslation({0, 0}));
313 draw(paint, 300, 0);
314
315 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
316}
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27

◆ TEST_P() [79/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderStrokePathThatEndsAtSharpTurn   
)

Definition at line 76 of file aiks_path_unittests.cc.

76 {
77 Canvas canvas;
78
80 paint.color = Color::Red();
81 paint.style = Paint::Style::kStroke;
82 paint.stroke_width = 200;
83
84 Rect rect = Rect::MakeXYWH(100, 100, 200, 200);
85 PathBuilder builder;
86 builder.AddArc(rect, Degrees(0), Degrees(90), false);
87
88 canvas.DrawPath(builder.TakePath(), paint);
89 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
90}

◆ TEST_P() [80/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderStrokePathWithCubicLine   
)

Definition at line 92 of file aiks_path_unittests.cc.

92 {
93 Canvas canvas;
94
96 paint.color = Color::Red();
97 paint.style = Paint::Style::kStroke;
98 paint.stroke_width = 20;
99
100 PathBuilder builder;
101 builder.AddCubicCurve({0, 200}, {50, 400}, {350, 0}, {400, 200});
102
103 canvas.DrawPath(builder.TakePath(), paint);
104 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
105}

◆ TEST_P() [81/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderStrokes   
)

Definition at line 45 of file aiks_path_unittests.cc.

45 {
46 Canvas canvas;
48 paint.color = Color::Red();
49 paint.stroke_width = 20.0;
50 paint.style = Paint::Style::kStroke;
51 canvas.DrawPath(PathBuilder{}.AddLine({200, 100}, {800, 100}).TakePath(),
52 paint);
53 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
54}

◆ TEST_P() [82/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientClamp   
)

Definition at line 502 of file aiks_gradient_unittests.cc.

502 {
503 CanRenderSweepGradient(this, Entity::TileMode::kClamp);
504}

◆ TEST_P() [83/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientDecal   
)

Definition at line 511 of file aiks_gradient_unittests.cc.

511 {
512 CanRenderSweepGradient(this, Entity::TileMode::kDecal);
513}

◆ TEST_P() [84/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientManyColorsClamp   
)

Definition at line 549 of file aiks_gradient_unittests.cc.

549 {
550 CanRenderSweepGradientManyColors(this, Entity::TileMode::kClamp);
551}

◆ TEST_P() [85/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientManyColorsDecal   
)

Definition at line 558 of file aiks_gradient_unittests.cc.

558 {
559 CanRenderSweepGradientManyColors(this, Entity::TileMode::kDecal);
560}

◆ TEST_P() [86/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientManyColorsMirror   
)

Definition at line 555 of file aiks_gradient_unittests.cc.

555 {
556 CanRenderSweepGradientManyColors(this, Entity::TileMode::kMirror);
557}

◆ TEST_P() [87/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientManyColorsRepeat   
)

Definition at line 552 of file aiks_gradient_unittests.cc.

552 {
553 CanRenderSweepGradientManyColors(this, Entity::TileMode::kRepeat);
554}

◆ TEST_P() [88/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientMirror   
)

Definition at line 508 of file aiks_gradient_unittests.cc.

508 {
509 CanRenderSweepGradient(this, Entity::TileMode::kMirror);
510}

◆ TEST_P() [89/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientRepeat   
)

Definition at line 505 of file aiks_gradient_unittests.cc.

505 {
506 CanRenderSweepGradient(this, Entity::TileMode::kRepeat);
507}

◆ TEST_P() [90/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientWithDitheringDisabled   
)

Definition at line 158 of file aiks_gradient_unittests.cc.

158 {
160}
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test, bool use_dithering)

◆ TEST_P() [91/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderSweepGradientWithDitheringEnabled   
)

Definition at line 162 of file aiks_gradient_unittests.cc.

162 {
164}

◆ TEST_P() [92/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTextFrame   
)

Definition at line 735 of file aiks_unittests.cc.

735 {
736 Canvas canvas;
737 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
738 ASSERT_TRUE(RenderTextInCanvasSkia(
739 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
740 "Roboto-Regular.ttf"));
741 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
742}

◆ TEST_P() [93/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTextFrameSTB   
)

Definition at line 744 of file aiks_unittests.cc.

744 {
745 Canvas canvas;
746 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
747 ASSERT_TRUE(RenderTextInCanvasSTB(
748 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
749 "Roboto-Regular.ttf"));
750
751 SetTypographerContext(TypographerContextSTB::Make());
752 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
753}

◆ TEST_P() [94/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTextInSaveLayer   
)

Definition at line 850 of file aiks_unittests.cc.

850 {
851 Canvas canvas;
852 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
853
854 canvas.Translate({100, 100});
855 canvas.Scale(Vector2{0.5, 0.5});
856
857 // Blend the layer with the parent pass using kClear to expose the coverage.
858 canvas.SaveLayer({.blend_mode = BlendMode::kClear});
859 ASSERT_TRUE(RenderTextInCanvasSkia(
860 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
861 "Roboto-Regular.ttf"));
862 canvas.Restore();
863
864 // Render the text again over the cleared coverage rect.
865 ASSERT_TRUE(RenderTextInCanvasSkia(
866 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
867 "Roboto-Regular.ttf"));
868
869 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
870}
bool RenderTextInCanvasSkia(const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string_view &font_fixture, TextRenderOptions options={})

◆ TEST_P() [95/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTextOutsideBoundaries   
)

Definition at line 872 of file aiks_unittests.cc.

872 {
873 Canvas canvas;
874 canvas.Translate({200, 150});
875
876 // Construct the text blob.
877 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
878 ASSERT_NE(mapping, nullptr);
879
880 Scalar font_size = 80;
882 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
883
884 Paint text_paint;
885 text_paint.color = Color::Blue().WithAlpha(0.8);
886
887 struct {
888 Point position;
889 const char* text;
890 } text[] = {{Point(0, 0), "0F0F0F0"},
891 {Point(1, 2), "789"},
892 {Point(1, 3), "456"},
893 {Point(1, 4), "123"},
894 {Point(0, 6), "0F0F0F0"}};
895 for (auto& t : text) {
896 canvas.Save();
897 canvas.Translate(t.position * Point(font_size * 2, font_size * 1.1));
898 {
899 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
900 ASSERT_NE(blob, nullptr);
902 canvas.DrawTextFrame(frame, Point(), text_paint);
903 }
904 canvas.Restore();
905 }
906
907 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
908}

◆ TEST_P() [96/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderThickCurvedStrokes   
)

Definition at line 66 of file aiks_path_unittests.cc.

66 {
67 Canvas canvas;
69 paint.color = Color::Red();
70 paint.stroke_width = 100.0;
71 paint.style = Paint::Style::kStroke;
72 canvas.DrawPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath(), paint);
73 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
74}

◆ TEST_P() [97/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTiledTextureClamp   
)

Definition at line 202 of file aiks_unittests.cc.

202 {
203 CanRenderTiledTexture(this, Entity::TileMode::kClamp);
204}

◆ TEST_P() [98/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTiledTextureClampWithTranslate   
)

Definition at line 218 of file aiks_unittests.cc.

218 {
219 CanRenderTiledTexture(this, Entity::TileMode::kClamp,
220 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
221}

◆ TEST_P() [99/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTiledTextureDecal   
)

Definition at line 214 of file aiks_unittests.cc.

214 {
215 CanRenderTiledTexture(this, Entity::TileMode::kDecal);
216}

◆ TEST_P() [100/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTiledTextureMirror   
)

Definition at line 210 of file aiks_unittests.cc.

210 {
211 CanRenderTiledTexture(this, Entity::TileMode::kMirror);
212}

◆ TEST_P() [101/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTiledTextureRepeat   
)

Definition at line 206 of file aiks_unittests.cc.

206 {
207 CanRenderTiledTexture(this, Entity::TileMode::kRepeat);
208}

◆ TEST_P() [102/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderTinyOverlappingSubpasses   
)

This is a regression check for https://github.com/flutter/engine/pull/41129 The entire screen is green if successful. If failing, no frames will render, or the entire screen will be transparent black.

Definition at line 2204 of file aiks_unittests.cc.

2204 {
2205 Canvas canvas;
2206 canvas.DrawPaint({.color = Color::Red()});
2207
2208 // Draw two overlapping subpixel circles.
2209 canvas.SaveLayer({});
2210 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2211 canvas.Restore();
2212 canvas.SaveLayer({});
2213 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2214 canvas.Restore();
2215
2216 canvas.DrawPaint({.color = Color::Green()});
2217
2218 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2219}

◆ TEST_P() [103/435]

impeller::testing::TEST_P ( AiksTest  ,
CanRenderWithContiguousClipRestores   
)

Definition at line 368 of file aiks_unittests.cc.

368 {
369 Canvas canvas;
370
371 // Cover the whole canvas with red.
372 canvas.DrawPaint({.color = Color::Red()});
373
374 canvas.Save();
375
376 // Append two clips, the second resulting in empty coverage.
377 canvas.ClipPath(
378 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
379 canvas.ClipPath(
380 PathBuilder{}.AddRect(Rect::MakeXYWH(300, 300, 100, 100)).TakePath());
381
382 // Restore to no clips.
383 canvas.Restore();
384
385 // Replace the whole canvas with green.
386 canvas.DrawPaint({.color = Color::Green()});
387
388 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
389}

◆ TEST_P() [104/435]

impeller::testing::TEST_P ( AiksTest  ,
CanSaveLayerStandalone   
)

Definition at line 409 of file aiks_unittests.cc.

409 {
410 Canvas canvas;
411
412 Paint red;
413 red.color = Color::Red();
414
415 Paint alpha;
416 alpha.color = Color::Red().WithAlpha(0.5);
417
418 canvas.SaveLayer(alpha);
419
420 canvas.DrawCircle({125, 125}, 125, red);
421
422 canvas.Restore();
423
424 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
425}

◆ TEST_P() [105/435]

impeller::testing::TEST_P ( AiksTest  ,
CanvasCanPushPopCTM   
)

Definition at line 61 of file aiks_unittests.cc.

61 {
62 Canvas canvas;
63 ASSERT_EQ(canvas.GetSaveCount(), 1u);
64 ASSERT_EQ(canvas.Restore(), false);
65
66 canvas.Translate(Size{100, 100});
67 canvas.Save();
68 ASSERT_EQ(canvas.GetSaveCount(), 2u);
70 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
71 ASSERT_TRUE(canvas.Restore());
72 ASSERT_EQ(canvas.GetSaveCount(), 1u);
74 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
75}
const Matrix & GetCurrentTransform() const
Definition canvas.cc:296
size_t GetSaveCount() const
Definition canvas.cc:329

◆ TEST_P() [106/435]

impeller::testing::TEST_P ( AiksTest  ,
CanvasCTMCanBeUpdated   
)

Definition at line 52 of file aiks_unittests.cc.

52 {
53 Canvas canvas;
54 Matrix identity;
55 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), identity);
56 canvas.Translate(Size{100, 100});
58 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
59}

◆ TEST_P() [107/435]

impeller::testing::TEST_P ( AiksTest  ,
CaptureContext   
)

Definition at line 2625 of file aiks_unittests.cc.

2625 {
2626 auto capture_context = CaptureContext::MakeAllowlist({"TestDocument"});
2627
2628 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
2629 Canvas canvas;
2630
2631 capture_context.Rewind();
2632 auto document = capture_context.GetDocument("TestDocument");
2633
2634 auto color = document.AddColor("Background color", Color::CornflowerBlue());
2635 canvas.DrawPaint({.color = color});
2636
2637 if (AiksTest::ImGuiBegin("TestDocument", nullptr,
2638 ImGuiWindowFlags_AlwaysAutoResize)) {
2639 document.GetElement()->properties.Iterate([](CaptureProperty& property) {
2640 property.Invoke({.color = [](CaptureColorProperty& p) {
2641 ImGui::ColorEdit4(p.label.c_str(),
2642 reinterpret_cast<float*>(&p.value));
2643 }});
2644 });
2645 ImGui::End();
2646 }
2647
2648 return canvas.EndRecordingAsPicture();
2649 };
2650 OpenPlaygroundHere(callback);
2651}

◆ TEST_P() [108/435]

impeller::testing::TEST_P ( AiksTest  ,
CaptureInactivatedByDefault   
)

Definition at line 2653 of file aiks_unittests.cc.

2653 {
2654 ASSERT_FALSE(GetContext()->capture.IsActive());
2655}

◆ TEST_P() [109/435]

impeller::testing::TEST_P ( AiksTest  ,
ClearBlend   
)

Definition at line 356 of file aiks_blend_unittests.cc.

356 {
357 Canvas canvas;
358 Paint white;
359 white.color = Color::Blue();
360 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
361
362 Paint clear;
363 clear.blend_mode = BlendMode::kClear;
364
365 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
366}
BlendMode blend_mode
Definition paint.h:64

◆ TEST_P() [110/435]

impeller::testing::TEST_P ( AiksTest  ,
ClearBlendWithBlur   
)

Definition at line 183 of file aiks_blur_unittests.cc.

183 {
184 Canvas canvas;
185 Paint white;
186 white.color = Color::Blue();
187 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
188
189 Paint clear;
190 clear.blend_mode = BlendMode::kClear;
192 .style = FilterContents::BlurStyle::kNormal,
193 .sigma = Sigma(20),
194 };
195
196 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
197
198 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
199}
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition paint.h:69

◆ TEST_P() [111/435]

impeller::testing::TEST_P ( AiksTest  ,
ClearColorOptimizationDoesNotApplyForBackdropFilters   
)

Definition at line 1829 of file aiks_unittests.cc.

1829 {
1830 Canvas canvas;
1831 canvas.SaveLayer({}, std::nullopt,
1832 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1833 FilterContents::BlurStyle::kNormal,
1834 Entity::TileMode::kClamp));
1835 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1836 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1837 .blend_mode = BlendMode::kSourceOver});
1838 canvas.Restore();
1839
1841
1842 std::optional<Color> actual_color;
1843 bool found_subpass = false;
1844 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
1845 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1846 actual_color = subpass->get()->GetClearColor();
1847 found_subpass = true;
1848 }
1849 // Fail if the first element isn't a subpass.
1850 return true;
1851 });
1852
1853 EXPECT_TRUE(found_subpass);
1854 EXPECT_FALSE(actual_color.has_value());
1855}

◆ TEST_P() [112/435]

impeller::testing::TEST_P ( AiksTest  ,
ClearColorOptimizationWhenSubpassIsBiggerThanParentPass   
)

Definition at line 2853 of file aiks_unittests.cc.

2853 {
2854 SetWindowSize({400, 400});
2855 Canvas canvas;
2856 canvas.Scale(GetContentScale());
2857 canvas.DrawRect(Rect::MakeLTRB(200, 200, 300, 300), {.color = Color::Red()});
2858 canvas.SaveLayer({
2859 .image_filter = std::make_shared<MatrixImageFilter>(
2860 Matrix::MakeScale({2, 2, 1}), SamplerDescriptor{}),
2861 });
2862 // Draw a rectangle that would fully cover the parent pass size, but not
2863 // the subpass that it is rendered in.
2864 canvas.DrawRect(Rect::MakeLTRB(0, 0, 400, 400), {.color = Color::Green()});
2865 // Draw a bigger rectangle to force the subpass to be bigger.
2866 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 800), {.color = Color::Red()});
2867 canvas.Restore();
2868
2869 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2870}

◆ TEST_P() [113/435]

impeller::testing::TEST_P ( AiksTest  ,
ClippedBlurFilterRendersCorrectly   
)

Definition at line 168 of file aiks_blur_unittests.cc.

168 {
169 Canvas canvas;
170 canvas.Translate(Point(0, -400));
171 Paint paint;
172 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
173 .style = FilterContents::BlurStyle::kNormal,
174 .sigma = Radius{120 * 3},
175 };
176 paint.color = Color::Red();
177 PathBuilder builder{};
178 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
179 canvas.DrawPath(builder.TakePath(), paint);
180 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
181}

◆ TEST_P() [114/435]

impeller::testing::TEST_P ( AiksTest  ,
ClippedBlurFilterRendersCorrectlyInteractive   
)

Definition at line 146 of file aiks_blur_unittests.cc.

146 {
147 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
148 static PlaygroundPoint playground_point(Point(400, 400), 20,
149 Color::Green());
150 auto point = DrawPlaygroundPoint(playground_point);
151
152 Canvas canvas;
153 canvas.Translate(point - Point(400, 400));
154 Paint paint;
155 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
156 .style = FilterContents::BlurStyle::kNormal,
157 .sigma = Radius{120 * 3},
158 };
159 paint.color = Color::Red();
160 PathBuilder builder{};
161 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
162 canvas.DrawPath(builder.TakePath(), paint);
163 return canvas.EndRecordingAsPicture();
164 };
165 ASSERT_TRUE(OpenPlaygroundHere(callback));
166}
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition widgets.cc:9

◆ TEST_P() [115/435]

impeller::testing::TEST_P ( AiksTest  ,
ClipRectElidesNoOpClips   
)

Definition at line 1805 of file aiks_unittests.cc.

1805 {
1806 Canvas canvas(Rect::MakeXYWH(0, 0, 100, 100));
1807 canvas.ClipRect(Rect::MakeXYWH(0, 0, 100, 100));
1808 canvas.ClipRect(Rect::MakeXYWH(-100, -100, 300, 300));
1809 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1810 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1811 .blend_mode = BlendMode::kSourceOver});
1812
1813 Picture picture = canvas.EndRecordingAsPicture();
1814 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
1815 BlendMode::kSourceOver);
1816 ASSERT_EQ(picture.pass->GetClearColor(), expected);
1817
1818 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1819 std::shared_ptr<Context> real_context = GetContext();
1820 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1821 AiksContext renderer(mock_context, nullptr);
1822 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1823
1824 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1825 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1826 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1827}
static MockContext mock_context
Definition mock_epoxy.cc:51

◆ TEST_P() [116/435]

impeller::testing::TEST_P ( AiksTest  ,
ClipsUseCurrentTransform   
)

Definition at line 391 of file aiks_unittests.cc.

391 {
392 std::array<Color, 5> colors = {Color::White(), Color::Black(),
393 Color::SkyBlue(), Color::Red(),
394 Color::Yellow()};
395 Canvas canvas;
396 Paint paint;
397
398 canvas.Translate(Vector3(300, 300));
399 for (int i = 0; i < 15; i++) {
400 canvas.Scale(Vector3(0.8, 0.8));
401
402 paint.color = colors[i % colors.size()];
403 canvas.ClipPath(PathBuilder{}.AddCircle({0, 0}, 300).TakePath());
404 canvas.DrawRect(Rect::MakeXYWH(-300, -300, 600, 600), paint);
405 }
406 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
407}

◆ TEST_P() [117/435]

impeller::testing::TEST_P ( AiksTest  ,
CollapsedDrawPaintInSubpass   
)

Definition at line 1857 of file aiks_unittests.cc.

1857 {
1858 Canvas canvas;
1859 canvas.DrawPaint(
1860 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
1861 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
1862 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1863 .blend_mode = BlendMode::kSourceOver});
1864
1865 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1866}

◆ TEST_P() [118/435]

impeller::testing::TEST_P ( AiksTest  ,
CollapsedDrawPaintInSubpassBackdropFilter   
)

Definition at line 1868 of file aiks_unittests.cc.

1868 {
1869 // Bug: https://github.com/flutter/flutter/issues/131576
1870 Canvas canvas;
1871 canvas.DrawPaint(
1872 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
1873 canvas.SaveLayer({}, {},
1874 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
1875 FilterContents::BlurStyle::kNormal,
1876 Entity::TileMode::kDecal));
1877 canvas.DrawPaint(
1878 {.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSourceOver});
1879
1880 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1881}

◆ TEST_P() [119/435]

impeller::testing::TEST_P ( AiksTest  ,
ColorMatrixFilterSubpassCollapseOptimization   
)

Definition at line 1883 of file aiks_unittests.cc.

1883 {
1884 Canvas canvas;
1885
1886 canvas.SaveLayer({
1887 .color_filter =
1888 ColorFilter::MakeMatrix({.array =
1889 {
1890 -1.0, 0, 0, 1.0, 0, //
1891 0, -1.0, 0, 1.0, 0, //
1892 0, 0, -1.0, 1.0, 0, //
1893 1.0, 1.0, 1.0, 1.0, 0 //
1894 }}),
1895 });
1896
1897 canvas.Translate({500, 300, 0});
1898 canvas.Rotate(Radians(2 * kPi / 3));
1899 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
1900
1901 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1902}
void Rotate(Radians radians)
Definition canvas.cc:325

◆ TEST_P() [120/435]

impeller::testing::TEST_P ( AiksTest  ,
ColorWheel   
)

color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 -> cyan domain: r >= 0 (because modulo used is non euclidean)

Definition at line 205 of file aiks_blend_unittests.cc.

205 {
206 // Compare with https://fiddle.skia.org/c/@BlendModes
207
209
210 auto draw_color_wheel = [](Canvas& canvas) {
211 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
212 /// cyan domain: r >= 0 (because modulo used is non euclidean)
213 auto color_wheel_sampler = [](Radians r) {
214 Scalar x = r.radians / k2Pi + 1;
215
216 // https://www.desmos.com/calculator/6nhjelyoaj
217 auto color_cycle = [](Scalar x) {
218 Scalar cycle = std::fmod(x, 6.0f);
219 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
220 };
221 return Color(color_cycle(6 * x + 1), //
222 color_cycle(6 * x - 1), //
223 color_cycle(6 * x - 3), //
224 1);
225 };
226
227 Paint paint;
228 paint.blend_mode = BlendMode::kSourceOver;
229
230 // Draw a fancy color wheel for the backdrop.
231 // https://www.desmos.com/calculator/xw7kafthwd
232 const int max_dist = 900;
233 for (int i = 0; i <= 900; i++) {
234 Radians r(kPhi / k2Pi * i);
235 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
236 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
237
238 paint.color =
239 color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
240 Point position(distance * std::sin(r.radians),
241 -distance * std::cos(r.radians));
242
243 canvas.DrawCircle(position, 9 + normalized_distance * 3, paint);
244 }
245 };
246
247 std::shared_ptr<Image> color_wheel_image;
248 Matrix color_wheel_transform;
249
250 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
251 // UI state.
252 static bool cache_the_wheel = true;
253 static int current_blend_index = 3;
254 static float dst_alpha = 1;
255 static float src_alpha = 1;
256 static Color color0 = Color::Red();
257 static Color color1 = Color::Green();
258 static Color color2 = Color::Blue();
259
260 if (AiksTest::ImGuiBegin("Controls", nullptr,
261 ImGuiWindowFlags_AlwaysAutoResize)) {
262 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
263 ImGui::ListBox("Blending mode", &current_blend_index,
264 blend_modes.blend_mode_names.data(),
265 blend_modes.blend_mode_names.size());
266 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
267 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
268 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
269 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
270 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
271 ImGui::End();
272 }
273
274 static Point content_scale;
275 Point new_content_scale = GetContentScale();
276
277 if (!cache_the_wheel || new_content_scale != content_scale) {
278 content_scale = new_content_scale;
279
280 // Render the color wheel to an image.
281
282 Canvas canvas;
283 canvas.Scale(content_scale);
284
285 canvas.Translate(Vector2(500, 400));
286 canvas.Scale(Vector2(3, 3));
287
288 draw_color_wheel(canvas);
289 auto color_wheel_picture = canvas.EndRecordingAsPicture();
290 auto snapshot = color_wheel_picture.Snapshot(renderer);
291 if (!snapshot.has_value() || !snapshot->texture) {
292 return std::nullopt;
293 }
294 color_wheel_image = std::make_shared<Image>(snapshot->texture);
295 color_wheel_transform = snapshot->transform;
296 }
297
298 Canvas canvas;
299
300 // Blit the color wheel backdrop to the screen with managed alpha.
301 canvas.SaveLayer({.color = Color::White().WithAlpha(dst_alpha),
302 .blend_mode = BlendMode::kSource});
303 {
304 canvas.DrawPaint({.color = Color::White()});
305
306 canvas.Save();
307 canvas.Transform(color_wheel_transform);
308 canvas.DrawImage(color_wheel_image, Point(), Paint());
309 canvas.Restore();
310 }
311 canvas.Restore();
312
313 canvas.Scale(content_scale);
314 canvas.Translate(Vector2(500, 400));
315 canvas.Scale(Vector2(3, 3));
316
317 // Draw 3 circles to a subpass and blend it in.
318 canvas.SaveLayer(
319 {.color = Color::White().WithAlpha(src_alpha),
320 .blend_mode = blend_modes.blend_mode_values[current_blend_index]});
321 {
322 Paint paint;
323 paint.blend_mode = BlendMode::kPlus;
324 const Scalar x = std::sin(k2Pi / 3);
325 const Scalar y = -std::cos(k2Pi / 3);
326 paint.color = color0;
327 canvas.DrawCircle(Point(-x, y) * 45, 65, paint);
328 paint.color = color1;
329 canvas.DrawCircle(Point(0, -1) * 45, 65, paint);
330 paint.color = color2;
331 canvas.DrawCircle(Point(x, y) * 45, 65, paint);
332 }
333 canvas.Restore();
334
335 return canvas.EndRecordingAsPicture();
336 };
337
338 ASSERT_TRUE(OpenPlaygroundHere(callback));
339}
std::vector< const char * > blend_mode_names

◆ TEST_P() [121/435]

impeller::testing::TEST_P ( AiksTest  ,
CoordinateConversionsAreCorrect   
)

Definition at line 523 of file aiks_unittests.cc.

523 {
524 Canvas canvas;
525
526 // Render a texture directly.
527 {
528 Paint paint;
529 auto image =
530 std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
531 paint.color = Color::Red();
532
533 canvas.Save();
534 canvas.Translate({100, 200, 0});
535 canvas.Scale(Vector2{0.5, 0.5});
536 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
537 canvas.Restore();
538 }
539
540 // Render an offscreen rendered texture.
541 {
542 Paint red;
543 red.color = Color::Red();
544 Paint green;
545 green.color = Color::Green();
546 Paint blue;
547 blue.color = Color::Blue();
548
549 Paint alpha;
550 alpha.color = Color::Red().WithAlpha(0.5);
551
552 canvas.SaveLayer(alpha);
553
554 canvas.DrawRect(Rect::MakeXYWH(000, 000, 100, 100), red);
555 canvas.DrawRect(Rect::MakeXYWH(020, 020, 100, 100), green);
556 canvas.DrawRect(Rect::MakeXYWH(040, 040, 100, 100), blue);
557
558 canvas.Restore();
559 }
560
561 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
562}

◆ TEST_P() [122/435]

impeller::testing::TEST_P ( AiksTest  ,
CorrectClipDepthAssignedToEntities   
)

Definition at line 2962 of file aiks_unittests.cc.

2962 {
2963 Canvas canvas; // Depth 1 (base pass)
2964 canvas.DrawRRect(Rect::MakeLTRB(0, 0, 100, 100), {10, 10}, {}); // Depth 2
2965 canvas.Save();
2966 {
2967 canvas.ClipRRect(Rect::MakeLTRB(0, 0, 50, 50), {10, 10}, {}); // Depth 4
2968 canvas.SaveLayer({}); // Depth 4
2969 {
2970 canvas.DrawRRect(Rect::MakeLTRB(0, 0, 50, 50), {10, 10}, {}); // Depth 3
2971 }
2972 canvas.Restore(); // Restore the savelayer.
2973 }
2974 canvas.Restore(); // Depth 5 -- this will no longer append a restore entity
2975 // once we switch to the clip depth approach.
2976
2977 auto picture = canvas.EndRecordingAsPicture();
2978
2979 std::vector<uint32_t> expected = {
2980 2, // DrawRRect
2981 4, // ClipRRect -- Has a depth value equal to the max depth of all the
2982 // content it affect. In this case, the SaveLayer and all
2983 // its contents are affected.
2984 4, // SaveLayer -- The SaveLayer is drawn to the parent pass after its
2985 // contents are rendered, so it should have a depth value
2986 // greater than all its contents.
2987 3, // DrawRRect
2988 5, // Restore (no longer necessary when clipping on the depth buffer)
2989 };
2990
2991 std::vector<uint32_t> actual;
2992
2993 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
2994 if (auto* subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
2995 actual.push_back(subpass->get()->GetClipDepth());
2996 }
2997 if (Entity* entity = std::get_if<Entity>(&element)) {
2998 actual.push_back(entity->GetClipDepth());
2999 }
3000 return true;
3001 });
3002
3003 ASSERT_EQ(actual.size(), expected.size());
3004 for (size_t i = 0; i < expected.size(); i++) {
3005 EXPECT_EQ(expected[i], actual[i]) << "Index: " << i;
3006 }
3007}

◆ TEST_P() [123/435]

impeller::testing::TEST_P ( AiksTest  ,
CoverageOriginShouldBeAccountedForInSubpasses   
)

Definition at line 1422 of file aiks_unittests.cc.

1422 {
1423 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1424 Canvas canvas;
1425 canvas.Scale(GetContentScale());
1426
1427 Paint alpha;
1428 alpha.color = Color::Red().WithAlpha(0.5);
1429
1430 auto current = Point{25, 25};
1431 const auto offset = Point{25, 25};
1432 const auto size = Size(100, 100);
1433
1434 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1435 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1436 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1437 auto bounds = Rect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1438
1439 canvas.DrawRect(bounds, Paint{.color = Color::Yellow(),
1440 .stroke_width = 5.0f,
1441 .style = Paint::Style::kStroke});
1442
1443 canvas.SaveLayer(alpha, bounds);
1444
1445 canvas.DrawRect(Rect::MakeOriginSize(current, size),
1446 Paint{.color = Color::Red()});
1447 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1448 Paint{.color = Color::Green()});
1449 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1450 Paint{.color = Color::Blue()});
1451
1452 canvas.Restore();
1453
1454 return canvas.EndRecordingAsPicture();
1455 };
1456
1457 ASSERT_TRUE(OpenPlaygroundHere(callback));
1458}

◆ TEST_P() [124/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawAdvancedBlendPartlyOffscreen   
)

Definition at line 94 of file aiks_blend_unittests.cc.

94 {
95 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
96 Color{0.1294, 0.5882, 0.9529, 1.0}};
97 std::vector<Scalar> stops = {0.0, 1.0};
98
99 Paint paint = {
100 .color_source = ColorSource::MakeLinearGradient(
101 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
102 Entity::TileMode::kRepeat, Matrix::MakeScale(Vector3(0.3, 0.3, 0.3))),
103 .blend_mode = BlendMode::kLighten,
104 };
105
106 Canvas canvas;
107 canvas.DrawPaint({.color = Color::Blue()});
108 canvas.Scale(Vector2(2, 2));
109 canvas.ClipRect(Rect::MakeLTRB(0, 0, 200, 200));
110 canvas.DrawCircle({100, 100}, 100, paint);
111 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
112}

◆ TEST_P() [125/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawAtlasAdvancedAndTransform   
)

Definition at line 2415 of file aiks_unittests.cc.

2415 {
2416 // Draws the image as four squares stiched together.
2417 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
2418 auto size = atlas->GetSize();
2419 auto image = std::make_shared<Image>(atlas);
2420 // Divide image into four quadrants.
2421 Scalar half_width = size.width / 2;
2422 Scalar half_height = size.height / 2;
2423 std::vector<Rect> texture_coordinates = {
2424 Rect::MakeLTRB(0, 0, half_width, half_height),
2425 Rect::MakeLTRB(half_width, 0, size.width, half_height),
2426 Rect::MakeLTRB(0, half_height, half_width, size.height),
2427 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
2428 // Position quadrants adjacent to eachother.
2429 std::vector<Matrix> transforms = {
2430 Matrix::MakeTranslation({0, 0, 0}),
2431 Matrix::MakeTranslation({half_width, 0, 0}),
2432 Matrix::MakeTranslation({0, half_height, 0}),
2433 Matrix::MakeTranslation({half_width, half_height, 0})};
2434
2435 Paint paint;
2436
2437 Canvas canvas;
2438 canvas.Scale({0.25, 0.25, 1.0});
2439 canvas.DrawAtlas(image, transforms, texture_coordinates, {},
2440 BlendMode::kModulate, {}, std::nullopt, paint);
2441
2442 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2443}

◆ TEST_P() [126/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawAtlasPlusWideGamut   
)

Definition at line 3140 of file aiks_unittests.cc.

3140 {
3141 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
3142 PixelFormat::kB10G10R10A10XR);
3143
3144 // Draws the image as four squares stiched together.
3145 auto atlas =
3146 std::make_shared<Image>(CreateTextureForFixture("bay_bridge.jpg"));
3147 auto size = atlas->GetSize();
3148 // Divide image into four quadrants.
3149 Scalar half_width = size.width / 2;
3150 Scalar half_height = size.height / 2;
3151 std::vector<Rect> texture_coordinates = {
3152 Rect::MakeLTRB(0, 0, half_width, half_height),
3153 Rect::MakeLTRB(half_width, 0, size.width, half_height),
3154 Rect::MakeLTRB(0, half_height, half_width, size.height),
3155 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
3156 // Position quadrants adjacent to eachother.
3157 std::vector<Matrix> transforms = {
3158 Matrix::MakeTranslation({0, 0, 0}),
3159 Matrix::MakeTranslation({half_width, 0, 0}),
3160 Matrix::MakeTranslation({0, half_height, 0}),
3161 Matrix::MakeTranslation({half_width, half_height, 0})};
3162 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
3163 Color::Yellow()};
3164
3165 Canvas canvas;
3166 canvas.DrawAtlas(atlas, transforms, texture_coordinates, colors,
3167 BlendMode::kPlus, {}, std::nullopt, {});
3168
3169 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3170}

◆ TEST_P() [127/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawAtlasWithColorAdvancedAndTransform   
)

Definition at line 2382 of file aiks_unittests.cc.

2382 {
2383 // Draws the image as four squares stiched together.
2384 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
2385 auto size = atlas->GetSize();
2386 auto image = std::make_shared<Image>(atlas);
2387 // Divide image into four quadrants.
2388 Scalar half_width = size.width / 2;
2389 Scalar half_height = size.height / 2;
2390 std::vector<Rect> texture_coordinates = {
2391 Rect::MakeLTRB(0, 0, half_width, half_height),
2392 Rect::MakeLTRB(half_width, 0, size.width, half_height),
2393 Rect::MakeLTRB(0, half_height, half_width, size.height),
2394 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
2395 // Position quadrants adjacent to eachother.
2396 std::vector<Matrix> transforms = {
2397 Matrix::MakeTranslation({0, 0, 0}),
2398 Matrix::MakeTranslation({half_width, 0, 0}),
2399 Matrix::MakeTranslation({0, half_height, 0}),
2400 Matrix::MakeTranslation({half_width, half_height, 0})};
2401 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
2402 Color::Yellow()};
2403
2404 Paint paint;
2405
2406 Canvas canvas;
2407 canvas.Scale({0.25, 0.25, 1.0});
2408 canvas.DrawAtlas(image, transforms, texture_coordinates, colors,
2409 BlendMode::kModulate, {}, std::nullopt, paint);
2410
2411 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2412}

◆ TEST_P() [128/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawLinesRenderCorrectly   
)

Definition at line 250 of file aiks_path_unittests.cc.

250 {
251 Canvas canvas;
252 canvas.Scale(GetContentScale());
253 Paint paint;
254 paint.color = Color::Blue();
255 paint.stroke_width = 10;
256
257 auto draw = [&canvas](Paint& paint) {
258 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
259 paint.stroke_cap = cap;
260 Point origin = {100, 100};
261 Point p0 = {50, 0};
262 Point p1 = {150, 0};
263 canvas.DrawLine({150, 100}, {250, 100}, paint);
264 for (int d = 15; d < 90; d += 15) {
265 Matrix m = Matrix::MakeRotationZ(Degrees(d));
266 canvas.DrawLine(origin + m * p0, origin + m * p1, paint);
267 }
268 canvas.DrawLine({100, 150}, {100, 250}, paint);
269 canvas.DrawCircle({origin}, 35, paint);
270
271 canvas.DrawLine({250, 250}, {250, 250}, paint);
272
273 canvas.Translate({250, 0});
274 }
275 canvas.Translate({-750, 250});
276 };
277
278 std::vector<Color> colors = {
279 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
280 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
281 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
282 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
283 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
284 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
285 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
286 std::vector<Scalar> stops = {
287 0.0,
288 (1.0 / 6.0) * 1,
289 (1.0 / 6.0) * 2,
290 (1.0 / 6.0) * 3,
291 (1.0 / 6.0) * 4,
292 (1.0 / 6.0) * 5,
293 1.0,
294 };
295
296 auto texture = CreateTextureForFixture("airplane.jpg",
297 /*enable_mipmapping=*/true);
298
299 draw(paint);
300
301 paint.color_source = ColorSource::MakeRadialGradient(
302 {100, 100}, 200, std::move(colors), std::move(stops),
303 Entity::TileMode::kMirror, {});
304 draw(paint);
305
306 paint.color_source = ColorSource::MakeImage(
307 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
308 Matrix::MakeTranslation({-150, 75}));
309 draw(paint);
310
311 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
312}
void DrawLine(const Point &p0, const Point &p1, const Paint &paint)
Definition canvas.cc:483

◆ TEST_P() [129/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawPaintAbsorbsClears   
)

Definition at line 1678 of file aiks_unittests.cc.

1678 {
1679 Canvas canvas;
1680 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1681 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1682 .blend_mode = BlendMode::kSourceOver});
1683
1684 Picture picture = canvas.EndRecordingAsPicture();
1685 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
1686 BlendMode::kSourceOver);
1687 ASSERT_EQ(picture.pass->GetClearColor(), expected);
1688
1689 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1690 std::shared_ptr<Context> real_context = GetContext();
1691 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1692 AiksContext renderer(mock_context, nullptr);
1693 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1694
1695 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1696 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1697 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1698}

◆ TEST_P() [130/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawPaintTransformsBounds   
)

Definition at line 2322 of file aiks_unittests.cc.

2322 {
2323 auto runtime_stages = OpenAssetAsRuntimeStage("gradient.frag.iplr");
2324 auto runtime_stage =
2325 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2326 ASSERT_TRUE(runtime_stage);
2327 ASSERT_TRUE(runtime_stage->IsDirty());
2328
2329 struct FragUniforms {
2330 Size size;
2331 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
2332 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2333 uniform_data->resize(sizeof(FragUniforms));
2334 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2335
2336 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2337
2338 Paint paint;
2339 paint.color_source = ColorSource::MakeRuntimeEffect(
2340 runtime_stage, uniform_data, texture_inputs);
2341
2342 Canvas canvas;
2343 canvas.Save();
2344 canvas.Scale(GetContentScale());
2345 canvas.DrawPaint(paint);
2346 canvas.Restore();
2347
2348 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2349}

◆ TEST_P() [131/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawPaintWithAdvancedBlendOverFilter   
)

Definition at line 77 of file aiks_blend_unittests.cc.

77 {
78 Paint filtered = {
79 .color = Color::Black(),
80 .mask_blur_descriptor =
82 .style = FilterContents::BlurStyle::kNormal,
83 .sigma = Sigma(60),
84 },
85 };
86
87 Canvas canvas;
88 canvas.DrawPaint({.color = Color::White()});
89 canvas.DrawCircle({300, 300}, 200, filtered);
90 canvas.DrawPaint({.color = Color::Green(), .blend_mode = BlendMode::kScreen});
91 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
92}
filtered(names, to_skip)
Definition zip_utils.py:20

◆ TEST_P() [132/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawRectAbsorbsClears   
)

Definition at line 1725 of file aiks_unittests.cc.

1725 {
1726 Canvas canvas;
1727 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1728 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1729 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1730 {.color = Color::CornflowerBlue().WithAlpha(0.75),
1731 .blend_mode = BlendMode::kSourceOver});
1732
1733 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1734 Picture picture = canvas.EndRecordingAsPicture();
1735 std::shared_ptr<Context> real_context = GetContext();
1736 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1737 AiksContext renderer(mock_context, nullptr);
1738 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1739
1740 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1741 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1742 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1743}

◆ TEST_P() [133/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawRectAbsorbsClearsNegative   
)

Definition at line 1785 of file aiks_unittests.cc.

1785 {
1786 Canvas canvas;
1787 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1788 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1789 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1790 {.color = Color::CornflowerBlue().WithAlpha(0.75),
1791 .blend_mode = BlendMode::kSourceOver});
1792
1793 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1794 Picture picture = canvas.EndRecordingAsPicture();
1795 std::shared_ptr<Context> real_context = GetContext();
1796 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1797 AiksContext renderer(mock_context, nullptr);
1798 std::shared_ptr<Image> image = picture.ToImage(renderer, {301, 301});
1799
1800 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1801 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1802 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
1803}

◆ TEST_P() [134/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawRectAbsorbsClearsNegativeRotation   
)

Definition at line 1765 of file aiks_unittests.cc.

1765 {
1766 Canvas canvas;
1767 canvas.Translate(Vector3(150.0, 150.0, 0.0));
1768 canvas.Rotate(Degrees(45.0));
1769 canvas.Translate(Vector3(-150.0, -150.0, 0.0));
1770 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1771 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1772
1773 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1774 Picture picture = canvas.EndRecordingAsPicture();
1775 std::shared_ptr<Context> real_context = GetContext();
1776 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1777 AiksContext renderer(mock_context, nullptr);
1778 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1779
1780 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1781 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1782 ASSERT_EQ(render_pass->GetCommands().size(), 1llu);
1783}

◆ TEST_P() [135/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawRectAbsorbsClearsNegativeRRect   
)

Definition at line 1745 of file aiks_unittests.cc.

1745 {
1746 Canvas canvas;
1747 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
1748 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1749 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
1750 {.color = Color::CornflowerBlue().WithAlpha(0.75),
1751 .blend_mode = BlendMode::kSourceOver});
1752
1753 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1755 std::shared_ptr<Context> real_context = GetContext();
1756 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1757 AiksContext renderer(mock_context, nullptr);
1758 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1759
1760 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1761 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1762 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
1763}

◆ TEST_P() [136/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawRectStrokesRenderCorrectly   
)

Definition at line 314 of file aiks_path_unittests.cc.

314 {
315 Canvas canvas;
316 Paint paint;
317 paint.color = Color::Red();
318 paint.style = Paint::Style::kStroke;
319 paint.stroke_width = 10;
320
321 canvas.Translate({100, 100});
322 canvas.DrawPath(
323 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
324 {paint});
325
326 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
327}

◆ TEST_P() [137/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawRectStrokesWithBevelJoinRenderCorrectly   
)

Definition at line 329 of file aiks_path_unittests.cc.

329 {
330 Canvas canvas;
331 Paint paint;
332 paint.color = Color::Red();
333 paint.style = Paint::Style::kStroke;
334 paint.stroke_width = 10;
335 paint.stroke_join = Join::kBevel;
336
337 canvas.Translate({100, 100});
338 canvas.DrawPath(
339 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
340 {paint});
341
342 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
343}

◆ TEST_P() [138/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawScaledTextWithPerspectiveNoSaveLayer   
)

Definition at line 2573 of file aiks_unittests.cc.

2573 {
2574 Canvas canvas;
2575 canvas.Transform(Matrix(1.0, 0.0, 0.0, 0.0, //
2576 0.0, 1.0, 0.0, 0.0, //
2577 0.0, 0.0, 1.0, 0.01, //
2578 0.0, 0.0, 0.0, 1.0) * //
2579 Matrix::MakeRotationY({Degrees{10}}));
2580
2581 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
2582 "Roboto-Regular.ttf"));
2583
2584 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2585}

◆ TEST_P() [139/435]

impeller::testing::TEST_P ( AiksTest  ,
DrawScaledTextWithPerspectiveSaveLayer   
)

Definition at line 2587 of file aiks_unittests.cc.

2587 {
2588 Canvas canvas;
2589 Paint save_paint;
2590 canvas.SaveLayer(save_paint);
2591 canvas.Transform(Matrix(1.0, 0.0, 0.0, 0.0, //
2592 0.0, 1.0, 0.0, 0.0, //
2593 0.0, 0.0, 1.0, 0.01, //
2594 0.0, 0.0, 0.0, 1.0) * //
2595 Matrix::MakeRotationY({Degrees{10}}));
2596
2597 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
2598 "Roboto-Regular.ttf"));
2599 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2600}

◆ TEST_P() [140/435]

impeller::testing::TEST_P ( AiksTest  ,
EmptySaveLayerIgnoresPaint   
)

Definition at line 2872 of file aiks_unittests.cc.

2872 {
2873 Canvas canvas;
2874 canvas.Scale(GetContentScale());
2875 canvas.DrawPaint(Paint{.color = Color::Red()});
2876 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
2877 canvas.SaveLayer(Paint{.color = Color::Blue()});
2878 canvas.Restore();
2879 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2880}

◆ TEST_P() [141/435]

impeller::testing::TEST_P ( AiksTest  ,
EmptySaveLayerRendersWithClear   
)

Definition at line 2882 of file aiks_unittests.cc.

2882 {
2883 Canvas canvas;
2884 canvas.Scale(GetContentScale());
2885 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2886 canvas.DrawImage(image, {10, 10}, {});
2887 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
2888 canvas.SaveLayer(Paint{.blend_mode = BlendMode::kClear});
2889 canvas.Restore();
2890 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2891}

◆ TEST_P() [142/435]

impeller::testing::TEST_P ( AiksTest  ,
FilledCirclesRenderCorrectly   
)

Definition at line 994 of file aiks_unittests.cc.

994 {
995 Canvas canvas;
996 canvas.Scale(GetContentScale());
997 Paint paint;
998 const int color_count = 3;
999 Color colors[color_count] = {
1000 Color::Blue(),
1001 Color::Green(),
1002 Color::Crimson(),
1003 };
1004
1005 paint.color = Color::White();
1006 canvas.DrawPaint(paint);
1007
1008 int c_index = 0;
1009 int radius = 600;
1010 while (radius > 0) {
1011 paint.color = colors[(c_index++) % color_count];
1012 canvas.DrawCircle({10, 10}, radius, paint);
1013 if (radius > 30) {
1014 radius -= 10;
1015 } else {
1016 radius -= 2;
1017 }
1018 }
1019
1020 std::vector<Color> gradient_colors = {
1021 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1022 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1023 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1024 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1025 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1026 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1027 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1028 std::vector<Scalar> stops = {
1029 0.0,
1030 (1.0 / 6.0) * 1,
1031 (1.0 / 6.0) * 2,
1032 (1.0 / 6.0) * 3,
1033 (1.0 / 6.0) * 4,
1034 (1.0 / 6.0) * 5,
1035 1.0,
1036 };
1037 auto texture = CreateTextureForFixture("airplane.jpg",
1038 /*enable_mipmapping=*/true);
1039
1040 paint.color_source = ColorSource::MakeRadialGradient(
1041 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
1042 Entity::TileMode::kMirror, {});
1043 canvas.DrawCircle({500, 600}, 100, paint);
1044
1045 paint.color_source = ColorSource::MakeImage(
1046 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1047 Matrix::MakeTranslation({700, 200}));
1048 canvas.DrawCircle({800, 300}, 100, paint);
1049
1050 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1051}

◆ TEST_P() [143/435]

impeller::testing::TEST_P ( AiksTest  ,
FilledEllipsesRenderCorrectly   
)

Definition at line 1117 of file aiks_unittests.cc.

1117 {
1118 Canvas canvas;
1119 canvas.Scale(GetContentScale());
1120 Paint paint;
1121 const int color_count = 3;
1122 Color colors[color_count] = {
1123 Color::Blue(),
1124 Color::Green(),
1125 Color::Crimson(),
1126 };
1127
1128 paint.color = Color::White();
1129 canvas.DrawPaint(paint);
1130
1131 int c_index = 0;
1132 int long_radius = 600;
1133 int short_radius = 600;
1134 while (long_radius > 0 && short_radius > 0) {
1135 paint.color = colors[(c_index++) % color_count];
1136 canvas.DrawOval(Rect::MakeXYWH(10 - long_radius, 10 - short_radius,
1137 long_radius * 2, short_radius * 2),
1138 paint);
1139 canvas.DrawOval(Rect::MakeXYWH(1000 - short_radius, 750 - long_radius,
1140 short_radius * 2, long_radius * 2),
1141 paint);
1142 if (short_radius > 30) {
1143 short_radius -= 10;
1144 long_radius -= 5;
1145 } else {
1146 short_radius -= 2;
1147 long_radius -= 1;
1148 }
1149 }
1150
1151 std::vector<Color> gradient_colors = {
1152 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1153 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1154 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1155 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1156 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1157 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1158 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1159 std::vector<Scalar> stops = {
1160 0.0,
1161 (1.0 / 6.0) * 1,
1162 (1.0 / 6.0) * 2,
1163 (1.0 / 6.0) * 3,
1164 (1.0 / 6.0) * 4,
1165 (1.0 / 6.0) * 5,
1166 1.0,
1167 };
1168 auto texture = CreateTextureForFixture("airplane.jpg",
1169 /*enable_mipmapping=*/true);
1170
1171 paint.color = Color::White().WithAlpha(0.5);
1172
1173 paint.color_source = ColorSource::MakeRadialGradient(
1174 {300, 650}, 75, std::move(gradient_colors), std::move(stops),
1175 Entity::TileMode::kMirror, {});
1176 canvas.DrawOval(Rect::MakeXYWH(200, 625, 200, 50), paint);
1177 canvas.DrawOval(Rect::MakeXYWH(275, 550, 50, 200), paint);
1178
1179 paint.color_source = ColorSource::MakeImage(
1180 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1181 Matrix::MakeTranslation({610, 15}));
1182 canvas.DrawOval(Rect::MakeXYWH(610, 90, 200, 50), paint);
1183 canvas.DrawOval(Rect::MakeXYWH(685, 15, 50, 200), paint);
1184
1185 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1186}

◆ TEST_P() [144/435]

impeller::testing::TEST_P ( AiksTest  ,
FilledRoundRectPathsRenderCorrectly   
)

Definition at line 1332 of file aiks_unittests.cc.

1332 {
1333 Canvas canvas;
1334 canvas.Scale(GetContentScale());
1335 Paint paint;
1336 const int color_count = 3;
1337 Color colors[color_count] = {
1338 Color::Blue(),
1339 Color::Green(),
1340 Color::Crimson(),
1341 };
1342
1343 paint.color = Color::White();
1344 canvas.DrawPaint(paint);
1345
1346 auto draw_rrect_as_path = [&canvas](const Rect& rect, const Size& radii,
1347 const Paint& paint) {
1348 PathBuilder builder = PathBuilder();
1349 builder.AddRoundedRect(rect, radii);
1350 canvas.DrawPath(builder.TakePath(), paint);
1351 };
1352
1353 int c_index = 0;
1354 for (int i = 0; i < 4; i++) {
1355 for (int j = 0; j < 4; j++) {
1356 paint.color = colors[(c_index++) % color_count];
1357 draw_rrect_as_path(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1358 Size(i * 5 + 10, j * 5 + 10), paint);
1359 }
1360 }
1361 paint.color = colors[(c_index++) % color_count];
1362 draw_rrect_as_path(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1363 paint.color = colors[(c_index++) % color_count];
1364 draw_rrect_as_path(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1365
1366 std::vector<Color> gradient_colors = {
1367 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1368 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1369 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1370 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1371 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1372 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1373 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1374 std::vector<Scalar> stops = {
1375 0.0,
1376 (1.0 / 6.0) * 1,
1377 (1.0 / 6.0) * 2,
1378 (1.0 / 6.0) * 3,
1379 (1.0 / 6.0) * 4,
1380 (1.0 / 6.0) * 5,
1381 1.0,
1382 };
1383 auto texture = CreateTextureForFixture("airplane.jpg",
1384 /*enable_mipmapping=*/true);
1385
1386 paint.color = Color::White().WithAlpha(0.1);
1387 paint.color_source = ColorSource::MakeRadialGradient(
1388 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1389 for (int i = 1; i <= 10; i++) {
1390 int j = 11 - i;
1391 draw_rrect_as_path(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1392 550 + i * 20, 550 + j * 20),
1393 Size(i * 10, j * 10), paint);
1394 }
1395 paint.color = Color::White().WithAlpha(0.5);
1396 paint.color_source = ColorSource::MakeRadialGradient(
1397 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1398 Entity::TileMode::kMirror, {});
1399 draw_rrect_as_path(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1400 draw_rrect_as_path(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1401
1402 paint.color = Color::White().WithAlpha(0.1);
1403 paint.color_source = ColorSource::MakeImage(
1404 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1405 Matrix::MakeTranslation({520, 20}));
1406 for (int i = 1; i <= 10; i++) {
1407 int j = 11 - i;
1408 draw_rrect_as_path(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1409 720 + i * 20, 220 + j * 20),
1410 Size(i * 10, j * 10), paint);
1411 }
1412 paint.color = Color::White().WithAlpha(0.5);
1413 paint.color_source = ColorSource::MakeImage(
1414 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1415 Matrix::MakeTranslation({800, 300}));
1416 draw_rrect_as_path(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1417 draw_rrect_as_path(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1418
1419 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1420}

◆ TEST_P() [145/435]

impeller::testing::TEST_P ( AiksTest  ,
FilledRoundRectsRenderCorrectly   
)

Definition at line 1188 of file aiks_unittests.cc.

1188 {
1189 Canvas canvas;
1190 canvas.Scale(GetContentScale());
1191 Paint paint;
1192 const int color_count = 3;
1193 Color colors[color_count] = {
1194 Color::Blue(),
1195 Color::Green(),
1196 Color::Crimson(),
1197 };
1198
1199 paint.color = Color::White();
1200 canvas.DrawPaint(paint);
1201
1202 int c_index = 0;
1203 for (int i = 0; i < 4; i++) {
1204 for (int j = 0; j < 4; j++) {
1205 paint.color = colors[(c_index++) % color_count];
1206 canvas.DrawRRect(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1207 Size(i * 5 + 10, j * 5 + 10), paint);
1208 }
1209 }
1210 paint.color = colors[(c_index++) % color_count];
1211 canvas.DrawRRect(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1212 paint.color = colors[(c_index++) % color_count];
1213 canvas.DrawRRect(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1214
1215 std::vector<Color> gradient_colors = {
1216 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1217 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1218 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1219 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1220 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1221 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1222 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1223 std::vector<Scalar> stops = {
1224 0.0,
1225 (1.0 / 6.0) * 1,
1226 (1.0 / 6.0) * 2,
1227 (1.0 / 6.0) * 3,
1228 (1.0 / 6.0) * 4,
1229 (1.0 / 6.0) * 5,
1230 1.0,
1231 };
1232 auto texture = CreateTextureForFixture("airplane.jpg",
1233 /*enable_mipmapping=*/true);
1234
1235 paint.color = Color::White().WithAlpha(0.1);
1236 paint.color_source = ColorSource::MakeRadialGradient(
1237 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1238 for (int i = 1; i <= 10; i++) {
1239 int j = 11 - i;
1240 canvas.DrawRRect(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1241 550 + i * 20, 550 + j * 20),
1242 Size(i * 10, j * 10), paint);
1243 }
1244 paint.color = Color::White().WithAlpha(0.5);
1245 paint.color_source = ColorSource::MakeRadialGradient(
1246 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1247 Entity::TileMode::kMirror, {});
1248 canvas.DrawRRect(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1249 canvas.DrawRRect(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1250
1251 paint.color = Color::White().WithAlpha(0.1);
1252 paint.color_source = ColorSource::MakeImage(
1253 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1254 Matrix::MakeTranslation({520, 20}));
1255 for (int i = 1; i <= 10; i++) {
1256 int j = 11 - i;
1257 canvas.DrawRRect(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1258 720 + i * 20, 220 + j * 20),
1259 Size(i * 10, j * 10), paint);
1260 }
1261 paint.color = Color::White().WithAlpha(0.5);
1262 paint.color_source = ColorSource::MakeImage(
1263 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1264 Matrix::MakeTranslation({800, 300}));
1265 canvas.DrawRRect(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1266 canvas.DrawRRect(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1267
1268 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1269}

◆ TEST_P() [146/435]

impeller::testing::TEST_P ( AiksTest  ,
ForegroundAdvancedBlendAppliesTransformCorrectly   
)

Definition at line 566 of file aiks_blend_unittests.cc.

566 {
567 auto texture = CreateTextureForFixture("airplane.jpg",
568 /*enable_mipmapping=*/true);
569
570 Canvas canvas;
571 canvas.Rotate(Degrees(30));
572 canvas.DrawImage(std::make_shared<Image>(texture), {200, 200},
573 {.color_filter = ColorFilter::MakeBlend(
574 BlendMode::kColorDodge, Color::Orange())});
575
576 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
577}

◆ TEST_P() [147/435]

impeller::testing::TEST_P ( AiksTest  ,
ForegroundBlendSubpassCollapseOptimization   
)

Definition at line 341 of file aiks_blend_unittests.cc.

341 {
342 Canvas canvas;
343
344 canvas.SaveLayer({
345 .color_filter =
346 ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Red()),
347 });
348
349 canvas.Translate({500, 300, 0});
350 canvas.Rotate(Radians(2 * kPi / 3));
351 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
352
353 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
354}

◆ TEST_P() [148/435]

impeller::testing::TEST_P ( AiksTest  ,
ForegroundPipelineBlendAppliesTransformCorrectly   
)

Definition at line 553 of file aiks_blend_unittests.cc.

553 {
554 auto texture = CreateTextureForFixture("airplane.jpg",
555 /*enable_mipmapping=*/true);
556
557 Canvas canvas;
558 canvas.Rotate(Degrees(30));
559 canvas.DrawImage(std::make_shared<Image>(texture), {200, 200},
560 {.color_filter = ColorFilter::MakeBlend(BlendMode::kSourceIn,
561 Color::Orange())});
562
563 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
564}

◆ TEST_P() [149/435]

impeller::testing::TEST_P ( AiksTest  ,
FormatSRGB   
)

Definition at line 947 of file aiks_unittests.cc.

947 {
948 PixelFormat pixel_format =
949 GetContext()->GetCapabilities()->GetDefaultColorFormat();
950 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
951 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
952 << "pixel format: " << PixelFormatToString(pixel_format);
953}
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition formats.h:100
constexpr const char * PixelFormatToString(PixelFormat format)
Definition formats.h:141

◆ TEST_P() [150/435]

impeller::testing::TEST_P ( AiksTest  ,
FormatWideGamut   
)

Definition at line 942 of file aiks_unittests.cc.

942 {
943 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
944 PixelFormat::kB10G10R10A10XR);
945}

◆ TEST_P() [151/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurAllocatesCorrectMipCountRenderTarget   
)

Definition at line 1008 of file aiks_blur_unittests.cc.

1008 {
1009 size_t blur_required_mip_count =
1010 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1011
1012 Canvas canvas;
1013 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1014 canvas.SaveLayer({}, std::nullopt,
1015 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1016 FilterContents::BlurStyle::kNormal,
1017 Entity::TileMode::kClamp));
1018 canvas.Restore();
1019
1021 std::shared_ptr<RenderTargetCache> cache =
1022 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1023 AiksContext aiks_context(GetContext(), nullptr, cache);
1024 picture.ToImage(aiks_context, {100, 100});
1025
1026 size_t max_mip_count = 0;
1027 for (auto it = cache->GetRenderTargetDataBegin();
1028 it != cache->GetRenderTargetDataEnd(); ++it) {
1029 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1030 }
1031 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1032}
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
Definition switches.h:191

◆ TEST_P() [152/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurAnimatedBackdrop   
)

Definition at line 714 of file aiks_blur_unittests.cc.

714 {
715 // This test is for checking out how stable rendering is when content is
716 // translated underneath a blur. Animating under a blur can cause
717 // *shimmering* to happen as a result of pixel alignment.
718 // See also: https://github.com/flutter/flutter/issues/140193
719 auto boston = std::make_shared<Image>(
720 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true));
721 ASSERT_TRUE(boston);
722 int64_t count = 0;
723 Scalar sigma = 20.0;
724 Scalar freq = 0.1;
725 Scalar amp = 50.0;
726 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
727 if (AiksTest::ImGuiBegin("Controls", nullptr,
728 ImGuiWindowFlags_AlwaysAutoResize)) {
729 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
730 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
731 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
732 ImGui::End();
733 }
734
735 Canvas canvas;
736 canvas.Scale(GetContentScale());
737 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
738 canvas.DrawImage(boston,
739 Point(1024 / 2 - boston->GetSize().width / 2,
740 (768 / 2 - boston->GetSize().height / 2) + y),
741 {});
742 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
743 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
744 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
745 canvas.ClipRect(
746 Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
747 canvas.ClipRect(Rect::MakeLTRB(100, 100, 900, 700));
748 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
749 ImageFilter::MakeBlur(Sigma(sigma), Sigma(sigma),
750 FilterContents::BlurStyle::kNormal,
751 Entity::TileMode::kClamp));
752 count += 1;
753 return canvas.EndRecordingAsPicture();
754 };
755 ASSERT_TRUE(OpenPlaygroundHere(callback));
756}
#define M_PI
int count

◆ TEST_P() [153/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurAtPeripheryHorizontal   
)

Definition at line 469 of file aiks_blur_unittests.cc.

469 {
470 Canvas canvas;
471
472 canvas.Scale(GetContentScale());
473 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
474 canvas.DrawImageRect(
475 std::make_shared<Image>(boston),
476 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
477 Rect::MakeLTRB(0, 0, GetWindowSize().width, 100), Paint{});
478 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
479 Size(10, 10), Paint{.color = Color::Magenta()});
480 canvas.ClipRect(Rect::MakeLTRB(0, 50, GetWindowSize().width, 150));
481 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
482 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
483 FilterContents::BlurStyle::kNormal,
484 Entity::TileMode::kClamp));
485 canvas.Restore();
486 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
487}

◆ TEST_P() [154/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurAtPeripheryVertical   
)

Definition at line 451 of file aiks_blur_unittests.cc.

451 {
452 Canvas canvas;
453
454 canvas.Scale(GetContentScale());
455 canvas.DrawRRect(Rect::MakeLTRB(0, 0, GetWindowSize().width, 100),
456 Size(10, 10), Paint{.color = Color::LimeGreen()});
457 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
458 Size(10, 10), Paint{.color = Color::Magenta()});
459 canvas.ClipRect(Rect::MakeLTRB(100, 0, 200, GetWindowSize().height));
460 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
461 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
462 FilterContents::BlurStyle::kNormal,
463 Entity::TileMode::kClamp));
464 canvas.Restore();
465
466 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
467}
int32_t height

◆ TEST_P() [155/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurBackdropTinyMipMap   
)

Definition at line 688 of file aiks_blur_unittests.cc.

688 {
689 for (int32_t i = 0; i < 5; ++i) {
690 Canvas canvas;
691 ISize clip_size = ISize(i, i);
692 canvas.ClipRect(
693 Rect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
694 canvas.DrawCircle(
695 {400, 400}, 200,
696 {
697 .color = Color::Green(),
698 .image_filter = ImageFilter::MakeBlur(
699 Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
700 Entity::TileMode::kDecal),
701 });
702 canvas.Restore();
703
704 Picture picture = canvas.EndRecordingAsPicture();
705 std::shared_ptr<RenderTargetCache> cache =
706 std::make_shared<RenderTargetCache>(
707 GetContext()->GetResourceAllocator());
708 AiksContext aiks_context(GetContext(), nullptr, cache);
709 std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
710 EXPECT_TRUE(image) << " clip rect " << i;
711 }
712}

◆ TEST_P() [156/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurMipMapImageFilter   
)

Definition at line 1073 of file aiks_blur_unittests.cc.

1073 {
1074 size_t blur_required_mip_count =
1075 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1076 fml::testing::LogCapture log_capture;
1077 Canvas canvas;
1078 canvas.SaveLayer(
1079 {.image_filter = ImageFilter::MakeBlur(Sigma(30), Sigma(30),
1080 FilterContents::BlurStyle::kNormal,
1081 Entity::TileMode::kClamp)});
1082 canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()});
1083
1085 std::shared_ptr<RenderTargetCache> cache =
1086 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1087 AiksContext aiks_context(GetContext(), nullptr, cache);
1088 picture.ToImage(aiks_context, {1024, 768});
1089
1090 size_t max_mip_count = 0;
1091 for (auto it = cache->GetRenderTargetDataBegin();
1092 it != cache->GetRenderTargetDataEnd(); ++it) {
1093 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1094 }
1095 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1096 // The log is FML_DLOG, so only check in debug builds.
1097#ifndef NDEBUG
1098 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1099 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1100 std::string::npos);
1101 } else {
1102 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1103 std::string::npos);
1104 }
1105#endif
1106}
std::string str() const
Definition logging.cc:122

◆ TEST_P() [157/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurMipMapNestedLayer   
)

Definition at line 1034 of file aiks_blur_unittests.cc.

1034 {
1035 fml::testing::LogCapture log_capture;
1036 size_t blur_required_mip_count =
1037 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1038
1039 Canvas canvas;
1040 canvas.DrawPaint({.color = Color::Wheat()});
1041 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
1042 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1043 canvas.SaveLayer({}, std::nullopt,
1044 ImageFilter::MakeBlur(Sigma(30), Sigma(30),
1045 FilterContents::BlurStyle::kNormal,
1046 Entity::TileMode::kClamp));
1047 canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()});
1048
1050 std::shared_ptr<RenderTargetCache> cache =
1051 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1052 AiksContext aiks_context(GetContext(), nullptr, cache);
1053 picture.ToImage(aiks_context, {100, 100});
1054
1055 size_t max_mip_count = 0;
1056 for (auto it = cache->GetRenderTargetDataBegin();
1057 it != cache->GetRenderTargetDataEnd(); ++it) {
1058 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1059 }
1060 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1061 // The log is FML_DLOG, so only check in debug builds.
1062#ifndef NDEBUG
1063 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1064 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1065 std::string::npos);
1066 } else {
1067 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1068 std::string::npos);
1069 }
1070#endif
1071}

◆ TEST_P() [158/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurMipMapSolidColor   
)

Definition at line 1108 of file aiks_blur_unittests.cc.

1108 {
1109 size_t blur_required_mip_count =
1110 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1111 fml::testing::LogCapture log_capture;
1112 Canvas canvas;
1113 canvas.DrawPath(PathBuilder{}
1114 .MoveTo({100, 100})
1115 .LineTo({200, 100})
1116 .LineTo({150, 200})
1117 .LineTo({50, 200})
1118 .Close()
1119 .TakePath(),
1120 {.color = Color::Chartreuse(),
1121 .image_filter = ImageFilter::MakeBlur(
1122 Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal,
1123 Entity::TileMode::kClamp)});
1124
1126 std::shared_ptr<RenderTargetCache> cache =
1127 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1128 AiksContext aiks_context(GetContext(), nullptr, cache);
1129 picture.ToImage(aiks_context, {1024, 768});
1130
1131 size_t max_mip_count = 0;
1132 for (auto it = cache->GetRenderTargetDataBegin();
1133 it != cache->GetRenderTargetDataEnd(); ++it) {
1134 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1135 }
1136 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1137 // The log is FML_DLOG, so only check in debug builds.
1138#ifndef NDEBUG
1139 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1140 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1141 std::string::npos);
1142 } else {
1143 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1144 std::string::npos);
1145 }
1146#endif
1147}

◆ TEST_P() [159/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurOneDimension   
)

Definition at line 541 of file aiks_blur_unittests.cc.

541 {
542 Canvas canvas;
543
544 canvas.Scale(GetContentScale());
545 canvas.Scale({0.5, 0.5, 1.0});
546 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
547 canvas.DrawImage(std::make_shared<Image>(boston), Point(100, 100), Paint{});
548 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
549 ImageFilter::MakeBlur(Sigma(50.0), Sigma(0.0),
550 FilterContents::BlurStyle::kNormal,
551 Entity::TileMode::kClamp));
552 canvas.Restore();
553 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
554}

◆ TEST_P() [160/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurRotatedAndClipped   
)

Definition at line 560 of file aiks_blur_unittests.cc.

560 {
561 Canvas canvas;
562 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
563 Rect bounds =
564 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
565 Vector2 image_center = Vector2(bounds.GetSize() / 2);
566 Paint paint = {.image_filter =
567 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
568 FilterContents::BlurStyle::kNormal,
569 Entity::TileMode::kDecal)};
570 Vector2 clip_size = {150, 75};
571 Vector2 center = Vector2(1024, 768) / 2;
572 canvas.Scale(GetContentScale());
573 canvas.ClipRect(
574 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
575 canvas.Translate({center.x, center.y, 0});
576 canvas.Scale({0.6, 0.6, 1});
577 canvas.Rotate(Degrees(25));
578
579 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
580 /*dest=*/bounds.Shift(-image_center), paint);
581
582 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
583}
Optional< SkRect > bounds
Definition SkRecords.h:189

◆ TEST_P() [161/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurRotatedAndClippedInteractive   
)

Definition at line 609 of file aiks_blur_unittests.cc.

609 {
610 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
611
612 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
613 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
614 const Entity::TileMode tile_modes[] = {
615 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
616 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
617
618 static float rotation = 0;
619 static float scale = 0.6;
620 static int selected_tile_mode = 3;
621
622 if (AiksTest::ImGuiBegin("Controls", nullptr,
623 ImGuiWindowFlags_AlwaysAutoResize)) {
624 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
625 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
626 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
627 sizeof(tile_mode_names) / sizeof(char*));
628 ImGui::End();
629 }
630
631 Canvas canvas;
632 Rect bounds =
633 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
634 Vector2 image_center = Vector2(bounds.GetSize() / 2);
635 Paint paint = {.image_filter =
636 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
637 FilterContents::BlurStyle::kNormal,
638 tile_modes[selected_tile_mode])};
639 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
640 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
641 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
642 Vector2 center = Vector2(1024, 768) / 2;
643 canvas.Scale(GetContentScale());
644 canvas.ClipRect(
645 Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
646 canvas.Translate({center.x, center.y, 0});
647 canvas.Scale({scale, scale, 1});
648 canvas.Rotate(Degrees(rotation));
649
650 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
651 /*dest=*/bounds.Shift(-image_center), paint);
652 return canvas.EndRecordingAsPicture();
653 };
654
655 ASSERT_TRUE(OpenPlaygroundHere(callback));
656}

◆ TEST_P() [162/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurScaledAndClipped   
)

Definition at line 585 of file aiks_blur_unittests.cc.

585 {
586 Canvas canvas;
587 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
588 Rect bounds =
589 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
590 Vector2 image_center = Vector2(bounds.GetSize() / 2);
591 Paint paint = {.image_filter =
592 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
593 FilterContents::BlurStyle::kNormal,
594 Entity::TileMode::kDecal)};
595 Vector2 clip_size = {150, 75};
596 Vector2 center = Vector2(1024, 768) / 2;
597 canvas.Scale(GetContentScale());
598 canvas.ClipRect(
599 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
600 canvas.Translate({center.x, center.y, 0});
601 canvas.Scale({0.6, 0.6, 1});
602
603 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
604 /*dest=*/bounds.Shift(-image_center), paint);
605
606 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
607}

◆ TEST_P() [163/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurSetsMipCountOnPass   
)

Definition at line 995 of file aiks_blur_unittests.cc.

995 {
996 Canvas canvas;
997 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
998 canvas.SaveLayer({}, std::nullopt,
999 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1000 FilterContents::BlurStyle::kNormal,
1001 Entity::TileMode::kClamp));
1002 canvas.Restore();
1003
1005 EXPECT_EQ(4, picture.pass->GetRequiredMipCount());
1006}

◆ TEST_P() [164/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurSolidColorTinyMipMap   
)

Definition at line 661 of file aiks_blur_unittests.cc.

661 {
662 for (int32_t i = 1; i < 5; ++i) {
663 Canvas canvas;
664 Scalar fi = i;
665 canvas.DrawPath(
667 .MoveTo({100, 100})
668 .LineTo({100.f + fi, 100.f + fi})
669 .TakePath(),
670 {.color = Color::Chartreuse(),
671 .image_filter = ImageFilter::MakeBlur(
672 Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
673 Entity::TileMode::kClamp)});
674
676 std::shared_ptr<RenderTargetCache> cache =
677 std::make_shared<RenderTargetCache>(
678 GetContext()->GetResourceAllocator());
679 AiksContext aiks_context(GetContext(), nullptr, cache);
680 std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
681 EXPECT_TRUE(image) << " length " << i;
682 }
683}

◆ TEST_P() [165/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurStyleInner   
)

Definition at line 857 of file aiks_blur_unittests.cc.

857 {
858 Canvas canvas;
859 canvas.Scale(GetContentScale());
860
861 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
862
863 Paint paint;
864 paint.color = Color::Green();
865 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
866 .style = FilterContents::BlurStyle::kInner,
867 .sigma = Sigma(30),
868 };
869 canvas.DrawPath(PathBuilder()
870 .MoveTo({200, 200})
871 .LineTo({300, 400})
872 .LineTo({100, 400})
873 .Close()
874 .TakePath(),
875 paint);
876
877 // Draw another thing to make sure the clip area is reset.
878 Paint red;
879 red.color = Color::Red();
880 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
881
882 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
883}

◆ TEST_P() [166/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurStyleInnerGradient   
)

Definition at line 758 of file aiks_blur_unittests.cc.

758 {
759 Canvas canvas;
760 canvas.Scale(GetContentScale());
761
762 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
763
764 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
765 Color{0.7568, 0.2627, 0.2118, 1.0}};
766 std::vector<Scalar> stops = {0.0, 1.0};
767
768 Paint paint;
769 paint.color_source = ColorSource::MakeLinearGradient(
770 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
771 Entity::TileMode::kMirror, {});
772 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
773 .style = FilterContents::BlurStyle::kInner,
774 .sigma = Sigma(30),
775 };
776 canvas.DrawPath(PathBuilder()
777 .MoveTo({200, 200})
778 .LineTo({300, 400})
779 .LineTo({100, 400})
780 .Close()
781 .TakePath(),
782 paint);
783
784 // Draw another thing to make sure the clip area is reset.
785 Paint red;
786 red.color = Color::Red();
787 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
788 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
789}

◆ TEST_P() [167/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurStyleOuter   
)

Definition at line 885 of file aiks_blur_unittests.cc.

885 {
886 Canvas canvas;
887 canvas.Scale(GetContentScale());
888
889 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
890
891 Paint paint;
892 paint.color = Color::Green();
893 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
894 .style = FilterContents::BlurStyle::kOuter,
895 .sigma = Sigma(30),
896 };
897 canvas.DrawPath(PathBuilder()
898 .MoveTo({200, 200})
899 .LineTo({300, 400})
900 .LineTo({100, 400})
901 .Close()
902 .TakePath(),
903 paint);
904
905 // Draw another thing to make sure the clip area is reset.
906 Paint red;
907 red.color = Color::Red();
908 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
909
910 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
911}

◆ TEST_P() [168/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurStyleOuterGradient   
)

Definition at line 824 of file aiks_blur_unittests.cc.

824 {
825 Canvas canvas;
826 canvas.Scale(GetContentScale());
827
828 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
829
830 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
831 Color{0.7568, 0.2627, 0.2118, 1.0}};
832 std::vector<Scalar> stops = {0.0, 1.0};
833
834 Paint paint;
835 paint.color_source = ColorSource::MakeLinearGradient(
836 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
837 Entity::TileMode::kMirror, {});
838 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
839 .style = FilterContents::BlurStyle::kOuter,
840 .sigma = Sigma(30),
841 };
842 canvas.DrawPath(PathBuilder()
843 .MoveTo({200, 200})
844 .LineTo({300, 400})
845 .LineTo({100, 400})
846 .Close()
847 .TakePath(),
848 paint);
849
850 // Draw another thing to make sure the clip area is reset.
851 Paint red;
852 red.color = Color::Red();
853 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
854 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
855}

◆ TEST_P() [169/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurStyleSolid   
)

Definition at line 913 of file aiks_blur_unittests.cc.

913 {
914 Canvas canvas;
915 canvas.Scale(GetContentScale());
916
917 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
918
919 Paint paint;
920 paint.color = Color::Green();
921 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
922 .style = FilterContents::BlurStyle::kSolid,
923 .sigma = Sigma(30),
924 };
925 canvas.DrawPath(PathBuilder()
926 .MoveTo({200, 200})
927 .LineTo({300, 400})
928 .LineTo({100, 400})
929 .Close()
930 .TakePath(),
931 paint);
932
933 // Draw another thing to make sure the clip area is reset.
934 Paint red;
935 red.color = Color::Red();
936 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
937
938 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
939}

◆ TEST_P() [170/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurStyleSolidGradient   
)

Definition at line 791 of file aiks_blur_unittests.cc.

791 {
792 Canvas canvas;
793 canvas.Scale(GetContentScale());
794
795 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
796
797 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
798 Color{0.7568, 0.2627, 0.2118, 1.0}};
799 std::vector<Scalar> stops = {0.0, 1.0};
800
801 Paint paint;
802 paint.color_source = ColorSource::MakeLinearGradient(
803 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
804 Entity::TileMode::kMirror, {});
805 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
806 .style = FilterContents::BlurStyle::kSolid,
807 .sigma = Sigma(30),
808 };
809 canvas.DrawPath(PathBuilder()
810 .MoveTo({200, 200})
811 .LineTo({300, 400})
812 .LineTo({100, 400})
813 .Close()
814 .TakePath(),
815 paint);
816
817 // Draw another thing to make sure the clip area is reset.
818 Paint red;
819 red.color = Color::Red();
820 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
821 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
822}

◆ TEST_P() [171/435]

impeller::testing::TEST_P ( AiksTest  ,
GaussianBlurWithoutDecalSupport   
)

Definition at line 493 of file aiks_blur_unittests.cc.

493 {
494 if (GetParam() != PlaygroundBackend::kMetal) {
495 GTEST_SKIP_(
496 "This backend doesn't yet support setting device capabilities.");
497 }
498 if (!WillRenderSomething()) {
499 // Sometimes these tests are run without playgrounds enabled which is
500 // pointless for this test since we are asserting that
501 // `SupportsDecalSamplerAddressMode` is called.
502 GTEST_SKIP_("This test requires playgrounds.");
503 }
504
505 std::shared_ptr<const Capabilities> old_capabilities =
506 GetContext()->GetCapabilities();
507 auto mock_capabilities = std::make_shared<MockCapabilities>();
508 EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode())
509 .Times(::testing::AtLeast(1))
510 .WillRepeatedly(::testing::Return(false));
511 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
512 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
513 FLT_FORWARD(mock_capabilities, old_capabilities,
514 GetDefaultDepthStencilFormat);
515 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
516 FLT_FORWARD(mock_capabilities, old_capabilities,
517 SupportsImplicitResolvingMSAA);
518 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
519 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch);
520 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
521 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
522 FLT_FORWARD(mock_capabilities, old_capabilities,
523 SupportsTextureToTextureBlits);
524 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
525 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
526
527 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
528 Canvas canvas;
529 canvas.Scale(GetContentScale() * 0.5);
530 canvas.DrawPaint({.color = Color::Black()});
531 canvas.DrawImage(
532 texture, Point(200, 200),
533 {
534 .image_filter = ImageFilter::MakeBlur(
535 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
536 Entity::TileMode::kDecal),
537 });
538 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
539}
static bool ok(int result)
#define FLT_FORWARD(mock, real, method)

◆ TEST_P() [172/435]

impeller::testing::TEST_P ( AiksTest  ,
GradientStrokesRenderCorrectly   
)

Definition at line 654 of file aiks_gradient_unittests.cc.

654 {
655 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
656 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
657 static float scale = 3;
658 static bool add_circle_clip = true;
659 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
660 const Entity::TileMode tile_modes[] = {
661 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
662 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
663 static int selected_tile_mode = 0;
664 static float alpha = 1;
665
666 if (AiksTest::ImGuiBegin("Controls", nullptr,
667 ImGuiWindowFlags_AlwaysAutoResize)) {
668 ImGui::SliderFloat("Scale", &scale, 0, 6);
669 ImGui::Checkbox("Circle clip", &add_circle_clip);
670 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
671 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
672 sizeof(tile_mode_names) / sizeof(char*));
673 ImGui::End();
674 }
675
676 Canvas canvas;
677 canvas.Scale(GetContentScale());
678 Paint paint;
679 paint.color = Color::White();
680 canvas.DrawPaint(paint);
681
682 paint.style = Paint::Style::kStroke;
683 paint.color = Color(1.0, 1.0, 1.0, alpha);
684 paint.stroke_width = 10;
685 auto tile_mode = tile_modes[selected_tile_mode];
686
687 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
688 Color{0.1294, 0.5882, 0.9529, 1.0}};
689 std::vector<Scalar> stops = {0.0, 1.0};
690
691 paint.color_source = ColorSource::MakeLinearGradient(
692 {0, 0}, {50, 50}, std::move(colors), std::move(stops), tile_mode, {});
693
694 Path path = PathBuilder{}
695 .MoveTo({20, 20})
696 .QuadraticCurveTo({60, 20}, {60, 60})
697 .Close()
698 .MoveTo({60, 20})
699 .QuadraticCurveTo({60, 60}, {20, 60})
700 .TakePath();
701
702 canvas.Scale(Vector2(scale, scale));
703
704 if (add_circle_clip) {
705 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
706 Color::Red());
707 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
708 Color::Red());
709 auto [handle_a, handle_b] =
710 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
711
712 auto screen_to_canvas = canvas.GetCurrentTransform().Invert();
713 Point point_a = screen_to_canvas * handle_a * GetContentScale();
714 Point point_b = screen_to_canvas * handle_b * GetContentScale();
715
716 Point middle = (point_a + point_b) / 2;
717 auto radius = point_a.GetDistance(middle);
718 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
719 }
720
721 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
722 paint.stroke_join = join;
723 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
724 paint.stroke_cap = cap;
725 canvas.DrawPath(path, paint);
726 canvas.Translate({80, 0});
727 }
728 canvas.Translate({-240, 60});
729 }
730
731 return canvas.EndRecordingAsPicture();
732 };
733
734 ASSERT_TRUE(OpenPlaygroundHere(callback));
735}
SINT Vec< 2 *N, T > join(const Vec< N, T > &lo, const Vec< N, T > &hi)
Definition SkVx.h:242
constexpr Type GetDistance(const TPoint &p) const
Definition point.h:200

◆ TEST_P() [173/435]

impeller::testing::TEST_P ( AiksTest  ,
GuassianBlurUpdatesMipmapContents   
)

Definition at line 967 of file aiks_blur_unittests.cc.

967 {
968 // This makes sure if mip maps are recycled across invocations of blurs the
969 // contents get updated each frame correctly. If they aren't updated the color
970 // inside the blur and outside the blur will be different.
971 //
972 // If there is some change to render target caching this could display a false
973 // positive in the future. Also, if the LOD that is rendered is 1 it could
974 // present a false positive.
975 int32_t count = 0;
976 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
977 Canvas canvas;
978 if (count++ == 0) {
979 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
980 } else {
981 canvas.DrawCircle({100, 100}, 50, {.color = Color::Chartreuse()});
982 }
983 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
984 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
985 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
986 FilterContents::BlurStyle::kNormal,
987 Entity::TileMode::kClamp));
988 canvas.Restore();
989 return canvas.EndRecordingAsPicture();
990 };
991
992 ASSERT_TRUE(OpenPlaygroundHere(callback));
993}

◆ TEST_P() [174/435]

impeller::testing::TEST_P ( AiksTest  ,
ImageColorSourceEffectTransform   
)

Definition at line 2915 of file aiks_unittests.cc.

2915 {
2916 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
2917
2918 Canvas canvas;
2919 auto texture = CreateTextureForFixture("monkey.png");
2920
2921 canvas.DrawPaint({.color = Color::White()});
2922
2923 // Translation
2924 {
2925 Paint paint;
2926 paint.color_source = ColorSource::MakeImage(
2927 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
2928 Matrix::MakeTranslation({50, 50}));
2929 canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint);
2930 }
2931
2932 // Rotation/skew
2933 {
2934 canvas.Save();
2935 canvas.Rotate(Degrees(45));
2936 Paint paint;
2937 paint.color_source = ColorSource::MakeImage(
2938 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
2939 Matrix(1, -1, 0, 0, //
2940 1, 1, 0, 0, //
2941 0, 0, 1, 0, //
2942 0, 0, 0, 1) //
2943 );
2944 canvas.DrawRect(Rect::MakeLTRB(100, 0, 200, 100), paint);
2945 canvas.Restore();
2946 }
2947
2948 // Scale
2949 {
2950 canvas.Translate(Vector2(100, 0));
2951 canvas.Scale(Vector2(100, 100));
2952 Paint paint;
2953 paint.color_source = ColorSource::MakeImage(
2954 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
2955 Matrix::MakeScale(Vector2(0.005, 0.005)));
2956 canvas.DrawRect(Rect::MakeLTRB(0, 0, 1, 1), paint);
2957 }
2958
2959 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2960}

◆ TEST_P() [175/435]

impeller::testing::TEST_P ( AiksTest  ,
ImageFilteredSaveLayerWithUnboundedContents   
)

Definition at line 1994 of file aiks_unittests.cc.

1994 {
1995 Canvas canvas;
1996 canvas.Scale(GetContentScale());
1997
1998 auto test = [&canvas](const std::shared_ptr<ImageFilter>& filter) {
1999 auto DrawLine = [&canvas](const Point& p0, const Point& p1,
2000 const Paint& p) {
2001 auto path = PathBuilder{}
2002 .AddLine(p0, p1)
2003 .SetConvexity(Convexity::kConvex)
2004 .TakePath();
2005 Paint paint = p;
2006 paint.style = Paint::Style::kStroke;
2007 canvas.DrawPath(path, paint);
2008 };
2009 // Registration marks for the edge of the SaveLayer
2010 DrawLine(Point(75, 100), Point(225, 100), {.color = Color::White()});
2011 DrawLine(Point(75, 200), Point(225, 200), {.color = Color::White()});
2012 DrawLine(Point(100, 75), Point(100, 225), {.color = Color::White()});
2013 DrawLine(Point(200, 75), Point(200, 225), {.color = Color::White()});
2014
2015 canvas.SaveLayer({.image_filter = filter},
2016 Rect::MakeLTRB(100, 100, 200, 200));
2017 {
2018 // DrawPaint to verify correct behavior when the contents are unbounded.
2019 canvas.DrawPaint({.color = Color::Yellow()});
2020
2021 // Contrasting rectangle to see interior blurring
2022 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
2023 {.color = Color::Blue()});
2024 }
2025 canvas.Restore();
2026 };
2027
2028 test(ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
2029 FilterContents::BlurStyle::kNormal,
2030 Entity::TileMode::kDecal));
2031
2032 canvas.Translate({200.0, 0.0});
2033
2034 test(ImageFilter::MakeDilate(Radius{10.0}, Radius{10.0}));
2035
2036 canvas.Translate({200.0, 0.0});
2037
2038 test(ImageFilter::MakeErode(Radius{10.0}, Radius{10.0}));
2039
2040 canvas.Translate({-400.0, 200.0});
2041
2042 auto rotate_filter =
2043 ImageFilter::MakeMatrix(Matrix::MakeTranslation({150, 150}) *
2044 Matrix::MakeRotationZ(Degrees{10.0}) *
2045 Matrix::MakeTranslation({-150, -150}),
2046 SamplerDescriptor{});
2047 test(rotate_filter);
2048
2049 canvas.Translate({200.0, 0.0});
2050
2051 auto rgb_swap_filter = ImageFilter::MakeFromColorFilter(
2052 *ColorFilter::MakeMatrix({.array = {
2053 0, 1, 0, 0, 0, //
2054 0, 0, 1, 0, 0, //
2055 1, 0, 0, 0, 0, //
2056 0, 0, 0, 1, 0 //
2057 }}));
2058 test(rgb_swap_filter);
2059
2060 canvas.Translate({200.0, 0.0});
2061
2062 test(ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter));
2063
2064 canvas.Translate({-400.0, 200.0});
2065
2066 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
2067 *rotate_filter));
2068
2069 canvas.Translate({200.0, 0.0});
2070
2071 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
2072 *rgb_swap_filter));
2073
2074 canvas.Translate({200.0, 0.0});
2075
2076 test(ImageFilter::MakeLocalMatrix(
2077 Matrix::MakeTranslation({25.0, 25.0}),
2078 *ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter)));
2079
2080 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2081}
PathBuilder & SetConvexity(Convexity value)

◆ TEST_P() [176/435]

impeller::testing::TEST_P ( AiksTest  ,
ImageFilteredUnboundedSaveLayerWithUnboundedContents   
)

Definition at line 2083 of file aiks_unittests.cc.

2083 {
2084 Canvas canvas;
2085 canvas.Scale(GetContentScale());
2086
2087 auto blur_filter = ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
2088 FilterContents::BlurStyle::kNormal,
2089 Entity::TileMode::kDecal);
2090
2091 canvas.SaveLayer({.image_filter = blur_filter}, std::nullopt);
2092 {
2093 // DrawPaint to verify correct behavior when the contents are unbounded.
2094 canvas.DrawPaint({.color = Color::Yellow()});
2095
2096 // Contrasting rectangle to see interior blurring
2097 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
2098 {.color = Color::Blue()});
2099 }
2100 canvas.Restore();
2101
2102 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2103}

◆ TEST_P() [177/435]

impeller::testing::TEST_P ( AiksTest  ,
LinearToSrgbFilterSubpassCollapseOptimization   
)

Definition at line 1904 of file aiks_unittests.cc.

1904 {
1905 Canvas canvas;
1906
1907 canvas.SaveLayer({
1908 .color_filter = ColorFilter::MakeLinearToSrgb(),
1909 });
1910
1911 canvas.Translate({500, 300, 0});
1912 canvas.Rotate(Radians(2 * kPi / 3));
1913 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
1914
1915 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1916}

◆ TEST_P() [178/435]

impeller::testing::TEST_P ( AiksTest  ,
MaskBlurDoesntStretchContents   
)

Definition at line 1149 of file aiks_blur_unittests.cc.

1149 {
1150 Scalar sigma = 70;
1151 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1152 if (AiksTest::ImGuiBegin("Controls", nullptr,
1153 ImGuiWindowFlags_AlwaysAutoResize)) {
1154 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
1155 ImGui::End();
1156 }
1157 Canvas canvas;
1158 canvas.Scale(GetContentScale());
1159 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1160
1161 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1162 ColorSource image_source = ColorSource::MakeImage(
1163 boston, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
1164
1165 canvas.Transform(Matrix::MakeTranslation({100, 100, 0}) *
1166 Matrix::MakeScale({0.5, 0.5, 1.0}));
1167 Paint paint = {
1168 .color_source = image_source,
1169 .mask_blur_descriptor =
1170 Paint::MaskBlurDescriptor{
1171 .style = FilterContents::BlurStyle::kNormal,
1172 .sigma = Sigma(sigma),
1173 },
1174 };
1175 canvas.DrawRect(
1176 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
1177 paint);
1178
1179 return canvas.EndRecordingAsPicture();
1180 };
1181 ASSERT_TRUE(OpenPlaygroundHere(callback));
1182}

◆ TEST_P() [179/435]

impeller::testing::TEST_P ( AiksTest  ,
MaskBlurTexture   
)

Definition at line 941 of file aiks_blur_unittests.cc.

941 {
942 Scalar sigma = 30;
943 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
944 if (AiksTest::ImGuiBegin("Controls", nullptr,
945 ImGuiWindowFlags_AlwaysAutoResize)) {
946 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
947 ImGui::End();
948 }
949 Canvas canvas;
950 canvas.Scale(GetContentScale());
951 Paint paint;
952 paint.color = Color::Green();
953 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
954 .style = FilterContents::BlurStyle::kNormal,
955 .sigma = Sigma(sigma),
956 };
957 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
958 canvas.DrawImage(std::make_shared<Image>(boston), {200, 200}, paint);
959 Paint red;
960 red.color = Color::Red();
961 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
962 return canvas.EndRecordingAsPicture();
963 };
964 ASSERT_TRUE(OpenPlaygroundHere(callback));
965}

◆ TEST_P() [180/435]

impeller::testing::TEST_P ( AiksTest  ,
MaskBlurWithZeroSigmaIsSkipped   
)

Definition at line 267 of file aiks_blur_unittests.cc.

267 {
268 Canvas canvas;
269
270 Paint paint = {
271 .color = Color::Blue(),
272 .mask_blur_descriptor =
274 .style = FilterContents::BlurStyle::kNormal,
275 .sigma = Sigma(0),
276 },
277 };
278
279 canvas.DrawCircle({300, 300}, 200, paint);
280 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
281
282 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
283}

◆ TEST_P() [181/435]

impeller::testing::TEST_P ( AiksTest  ,
MatrixBackdropFilter   
)

Definition at line 2538 of file aiks_unittests.cc.

2538 {
2539 Canvas canvas;
2540 canvas.DrawPaint({.color = Color::Black()});
2541 canvas.SaveLayer({}, std::nullopt);
2542 {
2543 canvas.DrawCircle(Point(200, 200), 100,
2544 {.color = Color::Green().WithAlpha(0.5),
2545 .blend_mode = BlendMode::kPlus});
2546 // Should render a second circle, centered on the bottom-right-most edge of
2547 // the circle.
2548 canvas.SaveLayer(
2549 {}, std::nullopt,
2550 ImageFilter::MakeMatrix(
2551 Matrix::MakeTranslation(Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
2552 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
2553 Matrix::MakeTranslation(Vector2(-100, -100)),
2554 SamplerDescriptor{}));
2555 canvas.Restore();
2556 }
2557 canvas.Restore();
2558
2559 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2560}

◆ TEST_P() [182/435]

impeller::testing::TEST_P ( AiksTest  ,
MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen   
)

Definition at line 2834 of file aiks_unittests.cc.

2835 {
2836 Canvas canvas;
2837 canvas.Scale(GetContentScale());
2838 canvas.Translate({100, 100});
2839 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
2840 // +300 translation applied by a SaveLayer image filter.
2841 canvas.SaveLayer({
2842 .image_filter = std::make_shared<MatrixImageFilter>(
2843 Matrix::MakeTranslation({300, 0}) * Matrix::MakeScale({2, 2, 2}),
2844 SamplerDescriptor{}),
2845 });
2846 canvas.DrawCircle({-150, 0}, 50, {.color = Color::Green()});
2847 canvas.Restore();
2848
2849 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2850}

◆ TEST_P() [183/435]

impeller::testing::TEST_P ( AiksTest  ,
MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen   
)

Definition at line 2817 of file aiks_unittests.cc.

2817 {
2818 Canvas canvas;
2819 canvas.Scale(GetContentScale());
2820 canvas.Translate({100, 100});
2821 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
2822 // +300 translation applied by a SaveLayer image filter.
2823 canvas.SaveLayer({
2824 .image_filter = std::make_shared<MatrixImageFilter>(
2825 Matrix::MakeTranslation({300, 0}), SamplerDescriptor{}),
2826 });
2827 canvas.DrawCircle({-300, 0}, 100, {.color = Color::Green()});
2828 canvas.Restore();
2829
2830 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2831}

◆ TEST_P() [184/435]

impeller::testing::TEST_P ( AiksTest  ,
MatrixImageFilterMagnify   
)

Definition at line 2800 of file aiks_unittests.cc.

2800 {
2801 Canvas canvas;
2802 canvas.Scale(GetContentScale());
2803 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2804 canvas.Translate({600, -200});
2805 canvas.SaveLayer({
2806 .image_filter = std::make_shared<MatrixImageFilter>(
2807 Matrix::MakeScale({2, 2, 2}), SamplerDescriptor{}),
2808 });
2809 canvas.DrawImage(image, {0, 0},
2810 Paint{.color = Color::White().WithAlpha(0.5)});
2811 canvas.Restore();
2812
2813 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2814}

◆ TEST_P() [185/435]

impeller::testing::TEST_P ( AiksTest  ,
MatrixSaveLayerFilter   
)

Definition at line 2511 of file aiks_unittests.cc.

2511 {
2512 Canvas canvas;
2513 canvas.DrawPaint({.color = Color::Black()});
2514 canvas.SaveLayer({}, std::nullopt);
2515 {
2516 canvas.DrawCircle(Point(200, 200), 100,
2517 {.color = Color::Green().WithAlpha(0.5),
2518 .blend_mode = BlendMode::kPlus});
2519 // Should render a second circle, centered on the bottom-right-most edge of
2520 // the circle.
2521 canvas.SaveLayer({.image_filter = ImageFilter::MakeMatrix(
2522 Matrix::MakeTranslation(Vector2(1, 1) *
2523 (200 + 100 * k1OverSqrt2)) *
2524 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
2525 Matrix::MakeTranslation(Vector2(-200, -200)),
2526 SamplerDescriptor{})},
2527 std::nullopt);
2528 canvas.DrawCircle(Point(200, 200), 100,
2529 {.color = Color::Green().WithAlpha(0.5),
2530 .blend_mode = BlendMode::kPlus});
2531 canvas.Restore();
2532 }
2533 canvas.Restore();
2534
2535 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2536}

◆ TEST_P() [186/435]

impeller::testing::TEST_P ( AiksTest  ,
MipmapGenerationWorksCorrectly   
)

Definition at line 3089 of file aiks_unittests.cc.

3089 {
3090 TextureDescriptor texture_descriptor;
3091 texture_descriptor.size = ISize{1024, 1024};
3092 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
3093 texture_descriptor.storage_mode = StorageMode::kHostVisible;
3094 texture_descriptor.mip_count = texture_descriptor.size.MipCount();
3095
3096 std::vector<uint8_t> bytes(4194304);
3097 bool alternate = false;
3098 for (auto i = 0u; i < 4194304; i += 4) {
3099 if (alternate) {
3100 bytes[i] = 255;
3101 bytes[i + 1] = 0;
3102 bytes[i + 2] = 0;
3103 bytes[i + 3] = 255;
3104 } else {
3105 bytes[i] = 0;
3106 bytes[i + 1] = 255;
3107 bytes[i + 2] = 0;
3108 bytes[i + 3] = 255;
3109 }
3110 alternate = !alternate;
3111 }
3112
3113 ASSERT_EQ(texture_descriptor.GetByteSizeOfBaseMipLevel(), bytes.size());
3114 auto mapping = std::make_shared<fml::NonOwnedMapping>(
3115 bytes.data(), // data
3116 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
3117 );
3118 auto texture =
3119 GetContext()->GetResourceAllocator()->CreateTexture(texture_descriptor);
3120
3121 ASSERT_TRUE(!!texture);
3122 ASSERT_TRUE(texture->SetContents(mapping));
3123
3124 auto command_buffer = GetContext()->CreateCommandBuffer();
3125 auto blit_pass = command_buffer->CreateBlitPass();
3126
3127 blit_pass->GenerateMipmap(texture);
3128 EXPECT_TRUE(blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()));
3129 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({command_buffer}).ok());
3130
3131 auto image = std::make_shared<Image>(texture);
3132
3133 Canvas canvas;
3134 canvas.DrawImageRect(image, Rect::MakeSize(texture->GetSize()),
3135 Rect::MakeLTRB(0, 0, 100, 100), {});
3136
3137 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3138}
constexpr size_t GetByteSizeOfBaseMipLevel() const

◆ TEST_P() [187/435]

impeller::testing::TEST_P ( AiksTest  ,
OpacityPeepHoleApplicationTest   
)

Definition at line 1639 of file aiks_unittests.cc.

1639 {
1640 auto entity_pass = std::make_shared<EntityPass>();
1641 auto rect = Rect::MakeLTRB(0, 0, 100, 100);
1642 Paint paint;
1643 paint.color = Color::White().WithAlpha(0.5);
1644 paint.color_filter =
1645 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
1646
1647 // Paint has color filter, can't elide.
1648 auto delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1649 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1650
1651 paint.color_filter = nullptr;
1652 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
1653 FilterContents::BlurStyle::kNormal,
1654 Entity::TileMode::kClamp);
1655
1656 // Paint has image filter, can't elide.
1657 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1658 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1659
1660 paint.image_filter = nullptr;
1661 paint.color = Color::Red();
1662
1663 // Paint has no alpha, can't elide;
1664 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1665 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1666
1667 // Positive test.
1668 Entity entity;
1669 entity.SetContents(SolidColorContents::Make(
1670 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
1671 entity_pass->AddEntity(std::move(entity));
1672 paint.color = Color::Red().WithAlpha(0.5);
1673
1674 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1675 ASSERT_TRUE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1676}

◆ TEST_P() [188/435]

impeller::testing::TEST_P ( AiksTest  ,
OpaqueEntitiesGetCoercedToSource   
)

Definition at line 2245 of file aiks_unittests.cc.

2245 {
2246 Canvas canvas;
2247 canvas.Scale(Vector2(1.618, 1.618));
2248 canvas.DrawCircle(Point(), 10,
2249 {
2250 .color = Color::CornflowerBlue(),
2251 .blend_mode = BlendMode::kSourceOver,
2252 });
2253 Picture picture = canvas.EndRecordingAsPicture();
2254
2255 // Extract the SolidColorSource.
2256 // Entity entity;
2257 std::vector<Entity> entity;
2258 std::shared_ptr<SolidColorContents> contents;
2259 picture.pass->IterateAllEntities([e = &entity, &contents](Entity& entity) {
2260 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
2261 contents =
2262 std::static_pointer_cast<SolidColorContents>(entity.GetContents());
2263 e->emplace_back(entity.Clone());
2264 return false;
2265 }
2266 return true;
2267 });
2268
2269 ASSERT_TRUE(entity.size() >= 1);
2270 ASSERT_TRUE(contents->IsOpaque());
2271 ASSERT_EQ(entity[0].GetBlendMode(), BlendMode::kSource);
2272}
static SkBlendMode GetBlendMode(SkSVGFeBlend::Mode mode)
Entity Clone() const
Definition entity.cc:195
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition entity.cc:46
constexpr Vector3 GetScale() const
Definition matrix.h:311

◆ TEST_P() [189/435]

impeller::testing::TEST_P ( AiksTest  ,
PaintBlendModeIsRespected   
)

Definition at line 114 of file aiks_blend_unittests.cc.

114 {
115 Paint paint;
116 Canvas canvas;
117 // Default is kSourceOver.
118 paint.color = Color(1, 0, 0, 0.5);
119 canvas.DrawCircle(Point(150, 200), 100, paint);
120 paint.color = Color(0, 1, 0, 0.5);
121 canvas.DrawCircle(Point(250, 200), 100, paint);
122
123 paint.blend_mode = BlendMode::kPlus;
124 paint.color = Color::Red();
125 canvas.DrawCircle(Point(450, 250), 100, paint);
126 paint.color = Color::Green();
127 canvas.DrawCircle(Point(550, 250), 100, paint);
128 paint.color = Color::Blue();
129 canvas.DrawCircle(Point(500, 150), 100, paint);
130 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
131}

◆ TEST_P() [190/435]

impeller::testing::TEST_P ( AiksTest  ,
PaintWithFilters   
)

Definition at line 1612 of file aiks_unittests.cc.

1612 {
1613 // validate that a paint with a color filter "HasFilters", no other filters
1614 // impact this setting.
1615 Paint paint;
1616
1617 ASSERT_FALSE(paint.HasColorFilter());
1618
1619 paint.color_filter =
1620 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
1621
1622 ASSERT_TRUE(paint.HasColorFilter());
1623
1624 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
1625 FilterContents::BlurStyle::kNormal,
1626 Entity::TileMode::kClamp);
1627
1628 ASSERT_TRUE(paint.HasColorFilter());
1629
1630 paint.mask_blur_descriptor = {};
1631
1632 ASSERT_TRUE(paint.HasColorFilter());
1633
1634 paint.color_filter = nullptr;
1635
1636 ASSERT_FALSE(paint.HasColorFilter());
1637}

◆ TEST_P() [191/435]

impeller::testing::TEST_P ( AiksTest  ,
ParentSaveLayerCreatesRenderPassWhenChildBackdropFilterIsPresent   
)

Definition at line 1702 of file aiks_unittests.cc.

1703 {
1704 Canvas canvas;
1705 canvas.SaveLayer({}, std::nullopt, ImageFilter::MakeMatrix(Matrix(), {}));
1706 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1707 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1708 .blend_mode = BlendMode::kSourceOver});
1709 canvas.Restore();
1710
1712
1713 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1714 std::shared_ptr<Context> real_context = GetContext();
1715 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1716 AiksContext renderer(mock_context, nullptr);
1717 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1718
1719 ASSERT_EQ(spy->render_passes_.size(),
1720 GetBackend() == PlaygroundBackend::kOpenGLES ? 4llu : 3llu);
1721 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1722 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1723}

◆ TEST_P() [192/435]

impeller::testing::TEST_P ( AiksTest  ,
PipelineBlendSingleParameter   
)

Definition at line 2602 of file aiks_unittests.cc.

2602 {
2603 Canvas canvas;
2604
2605 // Should render a green square in the middle of a blue circle.
2606 canvas.SaveLayer({});
2607 {
2608 canvas.Translate(Point(100, 100));
2609 canvas.DrawCircle(Point(200, 200), 200, {.color = Color::Blue()});
2610 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
2611 canvas.DrawCircle(Point(200, 200), 200,
2612 {
2613 .color = Color::Green(),
2614 .blend_mode = BlendMode::kSourceOver,
2615 .image_filter = ImageFilter::MakeFromColorFilter(
2616 *ColorFilter::MakeBlend(BlendMode::kDestination,
2617 Color::White())),
2618 });
2619 canvas.Restore();
2620 }
2621
2622 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2623}

◆ TEST_P() [193/435]

impeller::testing::TEST_P ( AiksTest  ,
ReleasesTextureOnTeardown   
)

Definition at line 2658 of file aiks_unittests.cc.

2658 {
2659 auto context = MakeContext();
2660 std::weak_ptr<Texture> weak_texture;
2661
2662 {
2663 auto texture = CreateTextureForFixture("table_mountain_nx.png");
2664
2665 Canvas canvas;
2666 canvas.Scale(GetContentScale());
2667 canvas.Translate({100.0f, 100.0f, 0});
2668
2669 Paint paint;
2670 paint.color_source = ColorSource::MakeImage(
2671 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {}, {});
2672 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
2673
2674 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2675 }
2676
2677 // See https://github.com/flutter/flutter/issues/134751.
2678 //
2679 // If the fence waiter was working this may not be released by the end of the
2680 // scope above. Adding a manual shutdown so that future changes to the fence
2681 // waiter will not flake this test.
2682 context->Shutdown();
2683
2684 // The texture should be released by now.
2685 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
2686 "by the backend, it should be "
2687 "released.";
2688}

◆ TEST_P() [194/435]

impeller::testing::TEST_P ( AiksTest  ,
RotateColorFilteredPath   
)

Definition at line 20 of file aiks_path_unittests.cc.

20 {
21 Canvas canvas;
22 canvas.Concat(Matrix::MakeTranslation({300, 300}));
23 canvas.Concat(Matrix::MakeRotationZ(Radians(kPiOver2)));
24 auto arrow_stem =
25 PathBuilder{}.MoveTo({120, 190}).LineTo({120, 50}).TakePath();
26 auto arrow_head = PathBuilder{}
27 .MoveTo({50, 120})
28 .LineTo({120, 190})
29 .LineTo({190, 120})
30 .TakePath();
31 auto paint = Paint{
32 .stroke_width = 15.0,
33 .stroke_cap = Cap::kRound,
34 .stroke_join = Join::kRound,
35 .style = Paint::Style::kStroke,
36 .color_filter =
37 ColorFilter::MakeBlend(BlendMode::kSourceIn, Color::AliceBlue()),
38 };
39
40 canvas.DrawPath(arrow_stem, paint);
41 canvas.DrawPath(arrow_head, paint);
42 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
43}
void Concat(const Matrix &transform)
Definition canvas.cc:280

◆ TEST_P() [195/435]

impeller::testing::TEST_P ( AiksTest  ,
SaveLayerDrawsBehindSubsequentEntities   
)

Definition at line 1460 of file aiks_unittests.cc.

1460 {
1461 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1462 Canvas canvas;
1463 Paint paint;
1464
1465 paint.color = Color::Black();
1466 Rect rect = Rect::MakeXYWH(25, 25, 25, 25);
1467 canvas.DrawRect(rect, paint);
1468
1469 canvas.Translate({10, 10});
1470 canvas.SaveLayer({});
1471
1472 paint.color = Color::Green();
1473 canvas.DrawRect(rect, paint);
1474
1475 canvas.Restore();
1476
1477 canvas.Translate({10, 10});
1478 paint.color = Color::Red();
1479 canvas.DrawRect(rect, paint);
1480
1481 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1482}

◆ TEST_P() [196/435]

impeller::testing::TEST_P ( AiksTest  ,
SaveLayerFiltersScaleWithTransform   
)

Definition at line 1541 of file aiks_unittests.cc.

1541 {
1542 Canvas canvas;
1543 canvas.Scale(GetContentScale());
1544 canvas.Translate(Vector2(100, 100));
1545
1546 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
1547 auto draw_image_layer = [&canvas, &texture](const Paint& paint) {
1548 canvas.SaveLayer(paint);
1549 canvas.DrawImage(texture, {}, Paint{});
1550 canvas.Restore();
1551 };
1552
1553 Paint effect_paint;
1554 effect_paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1555 .style = FilterContents::BlurStyle::kNormal,
1556 .sigma = Sigma{6},
1557 };
1558 draw_image_layer(effect_paint);
1559
1560 canvas.Translate(Vector2(300, 300));
1561 canvas.Scale(Vector2(3, 3));
1562 draw_image_layer(effect_paint);
1563
1564 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1565}

◆ TEST_P() [197/435]

impeller::testing::TEST_P ( AiksTest  ,
SiblingSaveLayerBoundsAreRespected   
)

Definition at line 1484 of file aiks_unittests.cc.

1484 {
1485 Canvas canvas;
1486 Paint paint;
1487 Rect rect = Rect::MakeXYWH(0, 0, 1000, 1000);
1488
1489 // Black, green, and red squares offset by [10, 10].
1490 {
1491 canvas.SaveLayer({}, Rect::MakeXYWH(25, 25, 25, 25));
1492 paint.color = Color::Black();
1493 canvas.DrawRect(rect, paint);
1494 canvas.Restore();
1495 }
1496
1497 {
1498 canvas.SaveLayer({}, Rect::MakeXYWH(35, 35, 25, 25));
1499 paint.color = Color::Green();
1500 canvas.DrawRect(rect, paint);
1501 canvas.Restore();
1502 }
1503
1504 {
1505 canvas.SaveLayer({}, Rect::MakeXYWH(45, 45, 25, 25));
1506 paint.color = Color::Red();
1507 canvas.DrawRect(rect, paint);
1508 canvas.Restore();
1509 }
1510
1511 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1512}

◆ TEST_P() [198/435]

impeller::testing::TEST_P ( AiksTest  ,
SolidColorApplyColorFilter   
)

Definition at line 2562 of file aiks_unittests.cc.

2562 {
2563 auto contents = SolidColorContents();
2564 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2565 auto result = contents.ApplyColorFilter([](const Color& color) {
2566 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2567 });
2568 ASSERT_TRUE(result);
2569 ASSERT_COLOR_NEAR(contents.GetColor(),
2570 Color(0.424452, 0.828743, 0.79105, 0.9375));
2571}

◆ TEST_P() [199/435]

impeller::testing::TEST_P ( AiksTest  ,
SolidColorCirclesOvalsRRectsMaskBlurCorrectly   
)

Definition at line 1271 of file aiks_unittests.cc.

1271 {
1272 Canvas canvas;
1273 canvas.Scale(GetContentScale());
1274 Paint paint;
1275 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1276 .style = FilterContents::BlurStyle::kNormal,
1277 .sigma = Sigma{1},
1278 };
1279
1280 canvas.DrawPaint({.color = Color::White()});
1281
1282 paint.color = Color::Crimson();
1283 Scalar y = 100.0f;
1284 for (int i = 0; i < 5; i++) {
1285 Scalar x = (i + 1) * 100;
1286 Scalar radius = x / 10.0f;
1287 canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1288 radius, 60.0f - radius),
1289 paint);
1290 }
1291
1292 paint.color = Color::Blue();
1293 y += 100.0f;
1294 for (int i = 0; i < 5; i++) {
1295 Scalar x = (i + 1) * 100;
1296 Scalar radius = x / 10.0f;
1297 canvas.DrawCircle({x + 25, y + 25}, radius, paint);
1298 }
1299
1300 paint.color = Color::Green();
1301 y += 100.0f;
1302 for (int i = 0; i < 5; i++) {
1303 Scalar x = (i + 1) * 100;
1304 Scalar radius = x / 10.0f;
1305 canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1306 radius, 60.0f - radius),
1307 paint);
1308 }
1309
1310 paint.color = Color::Purple();
1311 y += 100.0f;
1312 for (int i = 0; i < 5; i++) {
1313 Scalar x = (i + 1) * 100;
1314 Scalar radius = x / 20.0f;
1315 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1316 {radius, radius}, //
1317 paint);
1318 }
1319
1320 paint.color = Color::Orange();
1321 y += 100.0f;
1322 for (int i = 0; i < 5; i++) {
1323 Scalar x = (i + 1) * 100;
1324 Scalar radius = x / 20.0f;
1325 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1326 {radius, 5.0f}, paint);
1327 }
1328
1329 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1330}

◆ TEST_P() [200/435]

impeller::testing::TEST_P ( AiksTest  ,
SolidStrokesRenderCorrectly   
)

Definition at line 181 of file aiks_path_unittests.cc.

181 {
182 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
183 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
184 static Color color = Color::Black().WithAlpha(0.5);
185 static float scale = 3;
186 static bool add_circle_clip = true;
187
188 if (AiksTest::ImGuiBegin("Controls", nullptr,
189 ImGuiWindowFlags_AlwaysAutoResize)) {
190 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
191 ImGui::SliderFloat("Scale", &scale, 0, 6);
192 ImGui::Checkbox("Circle clip", &add_circle_clip);
193 ImGui::End();
194 }
195
196 Canvas canvas;
197 canvas.Scale(GetContentScale());
198 Paint paint;
199
200 paint.color = Color::White();
201 canvas.DrawPaint(paint);
202
203 paint.color = color;
204 paint.style = Paint::Style::kStroke;
205 paint.stroke_width = 10;
206
207 Path path = PathBuilder{}
208 .MoveTo({20, 20})
209 .QuadraticCurveTo({60, 20}, {60, 60})
210 .Close()
211 .MoveTo({60, 20})
212 .QuadraticCurveTo({60, 60}, {20, 60})
213 .TakePath();
214
215 canvas.Scale(Vector2(scale, scale));
216
217 if (add_circle_clip) {
218 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
219 Color::Red());
220 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
221 Color::Red());
222 auto [handle_a, handle_b] =
223 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
224
225 auto screen_to_canvas = canvas.GetCurrentTransform().Invert();
226 Point point_a = screen_to_canvas * handle_a * GetContentScale();
227 Point point_b = screen_to_canvas * handle_b * GetContentScale();
228
229 Point middle = (point_a + point_b) / 2;
230 auto radius = point_a.GetDistance(middle);
231 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
232 }
233
234 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
235 paint.stroke_join = join;
236 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
237 paint.stroke_cap = cap;
238 canvas.DrawPath(path, paint);
239 canvas.Translate({80, 0});
240 }
241 canvas.Translate({-240, 60});
242 }
243
244 return canvas.EndRecordingAsPicture();
245 };
246
247 ASSERT_TRUE(OpenPlaygroundHere(callback));
248}

◆ TEST_P() [201/435]

impeller::testing::TEST_P ( AiksTest  ,
SrgbToLinearFilterSubpassCollapseOptimization   
)

Definition at line 1918 of file aiks_unittests.cc.

1918 {
1919 Canvas canvas;
1920
1921 canvas.SaveLayer({
1922 .color_filter = ColorFilter::MakeSrgbToLinear(),
1923 });
1924
1925 canvas.Translate({500, 300, 0});
1926 canvas.Rotate(Radians(2 * kPi / 3));
1927 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
1928
1929 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1930}

◆ TEST_P() [202/435]

impeller::testing::TEST_P ( AiksTest  ,
StrokedCirclesRenderCorrectly   
)

Definition at line 1053 of file aiks_unittests.cc.

1053 {
1054 Canvas canvas;
1055 canvas.Scale(GetContentScale());
1056 Paint paint;
1057 const int color_count = 3;
1058 Color colors[color_count] = {
1059 Color::Blue(),
1060 Color::Green(),
1061 Color::Crimson(),
1062 };
1063
1064 paint.color = Color::White();
1065 canvas.DrawPaint(paint);
1066
1067 int c_index = 0;
1068
1069 auto draw = [&paint, &colors, &c_index](Canvas& canvas, Point center,
1070 Scalar r, Scalar dr, int n) {
1071 for (int i = 0; i < n; i++) {
1072 paint.color = colors[(c_index++) % color_count];
1073 canvas.DrawCircle(center, r, paint);
1074 r += dr;
1075 }
1076 };
1077
1078 paint.style = Paint::Style::kStroke;
1079 paint.stroke_width = 1;
1080 draw(canvas, {10, 10}, 2, 2, 14); // r = [2, 28], covers [1,29]
1081 paint.stroke_width = 5;
1082 draw(canvas, {10, 10}, 35, 10, 56); // r = [35, 585], covers [30,590]
1083
1084 std::vector<Color> gradient_colors = {
1085 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1086 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1087 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1088 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1089 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1090 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1091 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1092 std::vector<Scalar> stops = {
1093 0.0,
1094 (1.0 / 6.0) * 1,
1095 (1.0 / 6.0) * 2,
1096 (1.0 / 6.0) * 3,
1097 (1.0 / 6.0) * 4,
1098 (1.0 / 6.0) * 5,
1099 1.0,
1100 };
1101 auto texture = CreateTextureForFixture("airplane.jpg",
1102 /*enable_mipmapping=*/true);
1103
1104 paint.color_source = ColorSource::MakeRadialGradient(
1105 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
1106 Entity::TileMode::kMirror, {});
1107 draw(canvas, {500, 600}, 5, 10, 10);
1108
1109 paint.color_source = ColorSource::MakeImage(
1110 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1111 Matrix::MakeTranslation({700, 200}));
1112 draw(canvas, {800, 300}, 5, 10, 10);
1113
1114 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1115}

◆ TEST_P() [203/435]

impeller::testing::TEST_P ( AiksTest  ,
StrokedPathWithMoveToThenCloseDrawnCorrectly   
)

Definition at line 3173 of file aiks_unittests.cc.

3173 {
3174 Path path = PathBuilder{}
3175 .MoveTo({0, 400})
3176 .LineTo({0, 0})
3177 .LineTo({400, 0})
3178 // MoveTo implicitly adds a contour, ensure that close doesn't
3179 // add another nearly-empty contour.
3180 .MoveTo({0, 400})
3181 .Close()
3182 .TakePath();
3183
3184 Canvas canvas;
3185 canvas.Translate({50, 50, 0});
3186 canvas.DrawPath(path, {
3187 .color = Color::Blue(),
3188 .stroke_width = 10,
3189 .stroke_cap = Cap::kRound,
3190 .style = Paint::Style::kStroke,
3191 });
3192 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3193}

◆ TEST_P() [204/435]

impeller::testing::TEST_P ( AiksTest  ,
SubpassWithClearColorOptimization   
)

Definition at line 2893 of file aiks_unittests.cc.

2893 {
2894 Canvas canvas;
2895
2896 // Use a non-srcOver blend mode to ensure that we don't detect this as an
2897 // opacity peephole optimization.
2898 canvas.SaveLayer(
2899 {.color = Color::Blue().WithAlpha(0.5), .blend_mode = BlendMode::kSource},
2900 Rect::MakeLTRB(0, 0, 200, 200));
2901 canvas.DrawPaint(
2902 {.color = Color::BlackTransparent(), .blend_mode = BlendMode::kSource});
2903 canvas.Restore();
2904
2905 canvas.SaveLayer(
2906 {.color = Color::Blue(), .blend_mode = BlendMode::kDestinationOver});
2907 canvas.Restore();
2908
2909 // This playground should appear blank on CI since we are only drawing
2910 // transparent black. If the clear color optimization is broken, the texture
2911 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
2912 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2913}

◆ TEST_P() [205/435]

impeller::testing::TEST_P ( AiksTest  ,
TextForegroundShaderWithTransform   
)

Definition at line 2478 of file aiks_unittests.cc.

2478 {
2479 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
2480 ASSERT_NE(mapping, nullptr);
2481
2482 Scalar font_size = 100;
2484 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
2485
2486 Paint text_paint;
2487 text_paint.color = Color::Blue();
2488
2489 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
2490 Color{0.1294, 0.5882, 0.9529, 1.0}};
2491 std::vector<Scalar> stops = {
2492 0.0,
2493 1.0,
2494 };
2495 text_paint.color_source = ColorSource::MakeLinearGradient(
2496 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
2497 Entity::TileMode::kRepeat, {});
2498
2499 Canvas canvas;
2500 canvas.Translate({100, 100});
2501 canvas.Rotate(Radians(kPi / 4));
2502
2503 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
2504 ASSERT_NE(blob, nullptr);
2506 canvas.DrawTextFrame(frame, Point(), text_paint);
2507
2508 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2509}
ColorSource color_source
Definition paint.h:56

◆ TEST_P() [206/435]

impeller::testing::TEST_P ( AiksTest  ,
TextFrameSubpixelAlignment   
)

Definition at line 755 of file aiks_unittests.cc.

755 {
756 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
757 std::array<Scalar, 20> phase_offsets = {
758 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
759 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
760 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
761 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
762 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
763 static float font_size = 20;
764 static float phase_variation = 0.2;
765 static float speed = 0.5;
766 static float magnitude = 100;
767 if (AiksTest::ImGuiBegin("Controls", nullptr,
768 ImGuiWindowFlags_AlwaysAutoResize)) {
769 ImGui::SliderFloat("Font size", &font_size, 5, 50);
770 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
771 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
772 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
773 ImGui::End();
774 }
775
776 Canvas canvas;
777 canvas.Scale(GetContentScale());
778
779 for (size_t i = 0; i < phase_offsets.size(); i++) {
780 auto position =
781 Point(200 + magnitude *
782 std::sin((-phase_offsets[i] * k2Pi * phase_variation +
783 GetSecondsElapsed() * speed)), //
784 200 + i * font_size * 1.1 //
785 );
786 if (!RenderTextInCanvasSkia(
787 GetContext(), canvas,
788 "the quick brown fox jumped over "
789 "the lazy dog!.?",
790 "Roboto-Regular.ttf",
791 {.font_size = font_size, .position = position})) {
792 return std::nullopt;
793 }
794 }
795 return canvas.EndRecordingAsPicture();
796 };
797
798 ASSERT_TRUE(OpenPlaygroundHere(callback));
799}
static double magnitude(double a)

◆ TEST_P() [207/435]

impeller::testing::TEST_P ( AiksTest  ,
TextRotated   
)

Definition at line 910 of file aiks_unittests.cc.

910 {
911 Canvas canvas;
912 canvas.Scale(GetContentScale());
913 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
914
915 canvas.Transform(Matrix(0.25, -0.3, 0, -0.002, //
916 0, 0.5, 0, 0, //
917 0, 0, 0.3, 0, //
918 100, 100, 0, 1.3));
919 ASSERT_TRUE(RenderTextInCanvasSkia(
920 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
921 "Roboto-Regular.ttf"));
922
923 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
924}

◆ TEST_P() [208/435]

impeller::testing::TEST_P ( AiksTest  ,
TransformMultipliesCorrectly   
)

Definition at line 955 of file aiks_unittests.cc.

955 {
956 Canvas canvas;
958
959 // clang-format off
960 canvas.Translate(Vector3(100, 200));
962 canvas.GetCurrentTransform(),
963 Matrix( 1, 0, 0, 0,
964 0, 1, 0, 0,
965 0, 0, 1, 0,
966 100, 200, 0, 1));
967
968 canvas.Rotate(Radians(kPiOver2));
970 canvas.GetCurrentTransform(),
971 Matrix( 0, 1, 0, 0,
972 -1, 0, 0, 0,
973 0, 0, 1, 0,
974 100, 200, 0, 1));
975
976 canvas.Scale(Vector3(2, 3));
978 canvas.GetCurrentTransform(),
979 Matrix( 0, 2, 0, 0,
980 -3, 0, 0, 0,
981 0, 0, 0, 0,
982 100, 200, 0, 1));
983
984 canvas.Translate(Vector3(100, 200));
986 canvas.GetCurrentTransform(),
987 Matrix( 0, 2, 0, 0,
988 -3, 0, 0, 0,
989 0, 0, 0, 0,
990 -500, 400, 0, 1));
991 // clang-format on
992}

◆ TEST_P() [209/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerDrawsCorrectly   
)

Definition at line 1932 of file aiks_unittests.cc.

1932 {
1933 Canvas canvas;
1934
1935 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1936
1937 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
1938 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1939 canvas.Restore();
1940
1941 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1942}

◆ TEST_P() [210/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerImageDrawsCorrectly   
)

Definition at line 2105 of file aiks_unittests.cc.

2105 {
2106 Canvas canvas;
2107
2108 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2109 canvas.DrawImage(image, {100, 100}, {});
2110
2111 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2112 canvas.DrawImage(image, {100, 500}, {});
2113 canvas.Restore();
2114
2115 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2116}

◆ TEST_P() [211/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly   
)

Definition at line 2189 of file aiks_unittests.cc.

2189 {
2190 Canvas canvas;
2191 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), {.color = Color::Red()});
2192 canvas.SaveLayer({
2193 .color = Color::Black().WithAlpha(0.5),
2194 .blend_mode = BlendMode::kLighten,
2195 });
2196 canvas.DrawCircle({200, 200}, 100, {.color = Color::Green()});
2197 canvas.Restore();
2198 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2199}

◆ TEST_P() [212/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly   
)

Definition at line 1944 of file aiks_unittests.cc.

1944 {
1945 Canvas canvas;
1946
1947 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1948
1949 canvas.SaveLayer({
1950 .color = Color::Black().WithAlpha(0.5),
1951 .color_filter =
1952 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
1953 });
1954 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1955 canvas.Restore();
1956
1957 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1958}

◆ TEST_P() [213/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly   
)

Definition at line 1960 of file aiks_unittests.cc.

1960 {
1961 Canvas canvas;
1962
1963 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1964
1965 canvas.SaveLayer({
1966 .color = Color::Black().WithAlpha(0.5),
1967 .image_filter = ImageFilter::MakeFromColorFilter(
1968 *ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red())),
1969 });
1970
1971 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1972 canvas.Restore();
1973
1974 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1975}

◆ TEST_P() [214/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly   
)

Definition at line 1977 of file aiks_unittests.cc.

1977 {
1978 Canvas canvas;
1979
1980 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1981
1982 canvas.SaveLayer({
1983 .color = Color::Black().WithAlpha(0.5),
1984 .color_filter =
1985 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
1986 });
1987
1988 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1989 canvas.Restore();
1990
1991 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1992}

◆ TEST_P() [215/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly   
)

Definition at line 2163 of file aiks_unittests.cc.

2164 {
2165 Canvas canvas;
2166
2167 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2168 canvas.DrawImage(image, {100, 100}, {});
2169
2170 canvas.SaveLayer({
2171 .color = Color::Black().WithAlpha(0.5),
2172 .image_filter = ImageFilter::MakeFromColorFilter(
2173 *ColorFilter::MakeMatrix({.array =
2174 {
2175 1, 0, 0, 0, 0, //
2176 0, 1, 0, 0, 0, //
2177 0, 0.2, 1, 0, 0, //
2178 0, 0, 0, 0.5, 0 //
2179 }})),
2180 .color_filter =
2181 ColorFilter::MakeBlend(BlendMode::kModulate, Color::Green()),
2182 });
2183 canvas.DrawImage(image, {100, 500}, {});
2184 canvas.Restore();
2185
2186 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2187}

◆ TEST_P() [216/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly   
)

Definition at line 2118 of file aiks_unittests.cc.

2118 {
2119 Canvas canvas;
2120
2121 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2122 canvas.DrawImage(image, {100, 100}, {});
2123
2124 canvas.SaveLayer({
2125 .color = Color::Black().WithAlpha(0.5),
2126 .color_filter = ColorFilter::MakeMatrix({.array =
2127 {
2128 1, 0, 0, 0, 0, //
2129 0, 1, 0, 0, 0, //
2130 0, 0, 1, 0, 0, //
2131 0, 0, 0, 2, 0 //
2132 }}),
2133 });
2134 canvas.DrawImage(image, {100, 500}, {});
2135 canvas.Restore();
2136
2137 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2138}

◆ TEST_P() [217/435]

impeller::testing::TEST_P ( AiksTest  ,
TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly   
)

Definition at line 2140 of file aiks_unittests.cc.

2140 {
2141 Canvas canvas;
2142
2143 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2144 canvas.DrawImage(image, {100, 100}, {});
2145
2146 canvas.SaveLayer({
2147 .color = Color::Black().WithAlpha(0.5),
2148 .image_filter = ImageFilter::MakeFromColorFilter(
2149 *ColorFilter::MakeMatrix({.array =
2150 {
2151 1, 0, 0, 0, 0, //
2152 0, 1, 0, 0, 0, //
2153 0, 0, 1, 0, 0, //
2154 0, 0, 0, 2, 0 //
2155 }})),
2156 });
2157 canvas.DrawImage(image, {100, 500}, {});
2158 canvas.Restore();
2159
2160 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2161}

◆ TEST_P() [218/435]

impeller::testing::TEST_P ( AiksTest  ,
VerticesGeometryColorUVPositionData   
)

Definition at line 2736 of file aiks_unittests.cc.

2736 {
2737 Canvas canvas;
2738 Paint paint;
2739 auto texture = CreateTextureForFixture("table_mountain_nx.png");
2740
2741 paint.color_source =
2742 ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
2743 Entity::TileMode::kClamp, {}, Matrix());
2744
2745 auto vertices = {
2746 Point(0, 0),
2747 Point(texture->GetSize().width, 0),
2748 Point(0, texture->GetSize().height),
2749 Point(texture->GetSize().width, 0),
2750 Point(0, 0),
2751 Point(texture->GetSize().width, texture->GetSize().height),
2752 };
2753 std::vector<uint16_t> indices = {};
2754 std::vector<Point> texture_coordinates = {};
2755 std::vector<Color> vertex_colors = {
2756 Color::Red().WithAlpha(0.5), Color::Blue().WithAlpha(0.5),
2757 Color::Green().WithAlpha(0.5), Color::Red().WithAlpha(0.5),
2758 Color::Blue().WithAlpha(0.5), Color::Green().WithAlpha(0.5),
2759 };
2760 auto geometry = std::make_shared<VerticesGeometry>(
2761 vertices, indices, texture_coordinates, vertex_colors,
2762 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangles);
2763
2764 canvas.DrawVertices(geometry, BlendMode::kDestinationOver, paint);
2765 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2766}
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition canvas.cc:916

◆ TEST_P() [219/435]

impeller::testing::TEST_P ( AiksTest  ,
VerticesGeometryColorUVPositionDataAdvancedBlend   
)

Definition at line 2768 of file aiks_unittests.cc.

2768 {
2769 Canvas canvas;
2770 Paint paint;
2771 auto texture = CreateTextureForFixture("table_mountain_nx.png");
2772
2773 paint.color_source =
2774 ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
2775 Entity::TileMode::kClamp, {}, Matrix());
2776
2777 auto vertices = {
2778 Point(0, 0),
2779 Point(texture->GetSize().width, 0),
2780 Point(0, texture->GetSize().height),
2781 Point(texture->GetSize().width, 0),
2782 Point(0, 0),
2783 Point(texture->GetSize().width, texture->GetSize().height),
2784 };
2785 std::vector<uint16_t> indices = {};
2786 std::vector<Point> texture_coordinates = {};
2787 std::vector<Color> vertex_colors = {
2788 Color::Red().WithAlpha(0.5), Color::Blue().WithAlpha(0.5),
2789 Color::Green().WithAlpha(0.5), Color::Red().WithAlpha(0.5),
2790 Color::Blue().WithAlpha(0.5), Color::Green().WithAlpha(0.5),
2791 };
2792 auto geometry = std::make_shared<VerticesGeometry>(
2793 vertices, indices, texture_coordinates, vertex_colors,
2794 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangles);
2795
2796 canvas.DrawVertices(geometry, BlendMode::kColorBurn, paint);
2797 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2798}

◆ TEST_P() [220/435]

impeller::testing::TEST_P ( AiksTest  ,
VerticesGeometryUVPositionData   
)

Definition at line 2691 of file aiks_unittests.cc.

2691 {
2692 Canvas canvas;
2693 Paint paint;
2694 auto texture = CreateTextureForFixture("table_mountain_nx.png");
2695
2696 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
2697 Entity::TileMode::kClamp, {}, {});
2698
2699 auto vertices = {Point(0, 0), Point(texture->GetSize().width, 0),
2700 Point(0, texture->GetSize().height)};
2701 std::vector<uint16_t> indices = {0u, 1u, 2u};
2702 std::vector<Point> texture_coordinates = {};
2703 std::vector<Color> vertex_colors = {};
2704 auto geometry = std::make_shared<VerticesGeometry>(
2705 vertices, indices, texture_coordinates, vertex_colors,
2706 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangleStrip);
2707
2708 canvas.DrawVertices(geometry, BlendMode::kSourceOver, paint);
2709 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2710}

◆ TEST_P() [221/435]

impeller::testing::TEST_P ( AiksTest  ,
VerticesGeometryUVPositionDataWithTranslate   
)

Definition at line 2713 of file aiks_unittests.cc.

2713 {
2714 Canvas canvas;
2715 Paint paint;
2716 auto texture = CreateTextureForFixture("table_mountain_nx.png");
2717
2718 paint.color_source = ColorSource::MakeImage(
2719 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {},
2720 Matrix::MakeTranslation({100.0, 100.0}));
2721
2722 auto vertices = {Point(0, 0), Point(texture->GetSize().width, 0),
2723 Point(0, texture->GetSize().height)};
2724 std::vector<uint16_t> indices = {0u, 1u, 2u};
2725 std::vector<Point> texture_coordinates = {};
2726 std::vector<Color> vertex_colors = {};
2727 auto geometry = std::make_shared<VerticesGeometry>(
2728 vertices, indices, texture_coordinates, vertex_colors,
2729 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangleStrip);
2730
2731 canvas.DrawVertices(geometry, BlendMode::kSourceOver, paint);
2732 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2733}

◆ TEST_P() [222/435]

impeller::testing::TEST_P ( BlitPassTest  ,
BlitAcrossDifferentPixelFormatsFails   
)

Definition at line 18 of file blit_pass_unittests.cc.

18 {
19 ScopedValidationDisable scope; // avoid noise in output.
20 auto context = GetContext();
21 auto cmd_buffer = context->CreateCommandBuffer();
22 auto blit_pass = cmd_buffer->CreateBlitPass();
23
24 TextureDescriptor src_desc;
25 src_desc.format = PixelFormat::kA8UNormInt;
26 src_desc.size = {100, 100};
27 src_desc.storage_mode = StorageMode::kHostVisible;
28 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
29
30 TextureDescriptor dst_format;
31 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
32 dst_format.size = {100, 100};
33 dst_format.storage_mode = StorageMode::kHostVisible;
34 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
35
36 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
37}

◆ TEST_P() [223/435]

impeller::testing::TEST_P ( BlitPassTest  ,
BlitAcrossDifferentSampleCountsFails   
)

Definition at line 39 of file blit_pass_unittests.cc.

39 {
40 ScopedValidationDisable scope; // avoid noise in output.
41 auto context = GetContext();
42 auto cmd_buffer = context->CreateCommandBuffer();
43 auto blit_pass = cmd_buffer->CreateBlitPass();
44
45 TextureDescriptor src_desc;
46 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
47 src_desc.sample_count = SampleCount::kCount4;
48 src_desc.size = {100, 100};
49 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
50
51 TextureDescriptor dst_format;
52 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
53 dst_format.size = {100, 100};
54 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
55
56 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
57}

◆ TEST_P() [224/435]

impeller::testing::TEST_P ( BlitPassTest  ,
BlitPassesForMatchingFormats   
)

Definition at line 59 of file blit_pass_unittests.cc.

59 {
60 ScopedValidationDisable scope; // avoid noise in output.
61 auto context = GetContext();
62 auto cmd_buffer = context->CreateCommandBuffer();
63 auto blit_pass = cmd_buffer->CreateBlitPass();
64
65 TextureDescriptor src_desc;
66 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
67 src_desc.size = {100, 100};
68 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
69
70 TextureDescriptor dst_format;
71 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
72 dst_format.size = {100, 100};
73 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
74
75 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
76}

◆ TEST_P() [225/435]

impeller::testing::TEST_P ( ComputeSubgroupTest  ,
CapabilitiesSuportSubgroups   
)

Definition at line 42 of file compute_subgroup_unittests.cc.

42 {
43 auto context = GetContext();
44 ASSERT_TRUE(context);
45 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
46}

◆ TEST_P() [226/435]

impeller::testing::TEST_P ( ComputeSubgroupTest  ,
LargePath   
)

Definition at line 173 of file compute_subgroup_unittests.cc.

173 {
174 // The path in here is large enough to highlight issues around exceeding
175 // subgroup size.
176 using SS = StrokeComputeShader;
177
178 auto context = GetContext();
179 ASSERT_TRUE(context);
180 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
181 size_t vertex_count = 0;
182 Scalar stroke_width = 1.0;
183
184 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
185 context, "VertexBuffer");
186 auto vertex_buffer_count =
187 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
188 "VertexCount");
189
190 auto complex_path =
192 .MoveTo({359.934, 96.6335})
193 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
194 {354.673, 96.8895})
195 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
196 {354.367, 96.9075})
197 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
198 {349.259, 97.2355})
199 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
200 {348.625, 97.2834})
201 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
202 {343.789, 97.6722})
203 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
204 {342.703, 97.7734})
205 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
206 {338.246, 98.207})
207 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
208 {336.612, 98.3894})
209 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
210 {332.623, 98.8476})
211 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
212 {332.237, 98.8982})
213 .LineTo({332.237, 102.601})
214 .LineTo({321.778, 102.601})
215 .LineTo({321.778, 100.382})
216 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
217 {321.161, 100.476})
218 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
219 {315.332, 101.479})
220 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
221 {315.301, 101.484})
222 .LineTo({310.017, 105.94})
223 .LineTo({309.779, 105.427})
224 .LineTo({314.403, 101.651})
225 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
226 {314.368, 101.658})
227 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
228 {308.846, 102.748})
229 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
230 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
231 {303.425, 103.936})
232 .LineTo({299.105, 107.578})
233 .LineTo({298.867, 107.065})
234 .LineTo({302.394, 104.185})
235 .LineTo({302.412, 104.171})
236 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
237 {299.344, 104.921})
238 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
239 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
240 {291.462, 106.979})
241 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
242 {290.471, 107.257})
243 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
244 {287.449, 108.139})
245 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
246 {284.536, 109.035})
247 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
248 {281.952, 109.859})
249 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
250 {279.633, 110.638})
251 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
252 {276.803, 111.607})
253 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
254 {276.672, 111.653})
255 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
256 {271.721, 113.463})
257 .LineTo({271.717, 113.449})
258 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
259 {270.963, 113.628})
260 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
261 {270.748, 113.682})
262 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
263 {269.839, 113.926})
264 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
265 {269.681, 113.972})
266 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
267 {268.756, 114.239})
268 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
269 {268.367, 114.354})
270 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
271 {267.752, 114.54})
272 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
273 {253.564, 119.252})
274 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
275 {253.538, 119.261})
276 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
277 {248.189, 121.131})
278 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
279 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
280 {245.975, 121.912})
281 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
282 {244.698, 122.364})
283 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
284 {242.794, 123.04})
285 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
286 {240.961, 123.693})
287 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
288 {240.052, 124.018})
289 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
290 .LineTo({237.164, 125.003})
291 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
292 {235.81, 125.538})
293 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
294 {234.592, 125.977})
295 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
296 {234.59, 125.977})
297 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
298 {192.381, 141.429})
299 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
300 .LineTo({360, 160})
301 .LineTo({360, 119.256})
302 .LineTo({360, 106.332})
303 .LineTo({360, 96.6307})
304 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
305 {359.934, 96.6335})
306 .Close()
307 .TakePath();
308
309 auto callback = [&](RenderPass& pass) -> bool {
310 ::memset(vertex_buffer_count->OnGetContents(), 0,
311 sizeof(SS::VertexBufferCount));
312 ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));
313
314 ContentContext renderer(context, nullptr);
315 if (!renderer.IsValid()) {
316 return false;
317 }
318
319 ComputeTessellator{}
320 .SetStrokeWidth(stroke_width)
321 .Tessellate(
322 complex_path, renderer.GetTransientsBuffer(), context,
323 DeviceBuffer::AsBufferView(vertex_buffer),
324 DeviceBuffer::AsBufferView(vertex_buffer_count),
325 [vertex_buffer_count, &vertex_count](CommandBuffer::Status status) {
326 vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
327 vertex_buffer_count->OnGetContents())
328 ->count;
329 });
330
331 using VS = SolidFillPipeline::VertexShader;
332
333 pass.SetCommandLabel("Draw Stroke");
334 pass.SetStencilReference(0);
335
336 ContentContextOptions options;
337 options.sample_count = pass.GetRenderTarget().GetSampleCount();
338 options.color_attachment_pixel_format =
339 pass.GetRenderTarget().GetRenderTargetPixelFormat();
340 options.has_depth_stencil_attachments =
341 pass.GetRenderTarget().GetStencilAttachment().has_value();
342 options.blend_mode = BlendMode::kSourceIn;
343 options.primitive_type = PrimitiveType::kTriangleStrip;
344
345 options.stencil_mode =
346 ContentContextOptions::StencilMode::kOverdrawPreventionIncrement;
347
348 pass.SetPipeline(renderer.GetSolidFillPipeline(options));
349
350 auto count = reinterpret_cast<SS::VertexBufferCount*>(
351 vertex_buffer_count->OnGetContents())
352 ->count;
353
354 pass.SetVertexBuffer(
355 VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
356 .vertex_count = count,
357 .index_type = IndexType::kNone});
358
359 VS::FrameInfo frame_info;
360 auto world_matrix = Matrix::MakeScale(GetContentScale());
361 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
362 frame_info.color = Color::Red().Premultiply();
363 VS::BindFrameInfo(
364 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
365
366 return pass.Draw().ok();
367 };
368 ASSERT_TRUE(OpenPlaygroundHere(callback));
369}
SolidFillVertexShader VS
const Scalar stroke_width

◆ TEST_P() [227/435]

impeller::testing::TEST_P ( ComputeSubgroupTest  ,
PathPlayground   
)

Definition at line 48 of file compute_subgroup_unittests.cc.

48 {
49 // Renders stroked SVG paths in an interactive playground.
50 using SS = StrokeComputeShader;
51
52 auto context = GetContext();
53 ASSERT_TRUE(context);
54 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
55 char svg_path_data[16384] =
56 "M140 20 "
57 "C73 20 20 74 20 140 "
58 "c0 135 136 170 228 303 "
59 "88-132 229-173 229-303 "
60 "0-66-54-120-120-120 "
61 "-48 0-90 28-109 69 "
62 "-19-41-60-69-108-69z";
63 size_t vertex_count = 0;
64 Scalar stroke_width = 1.0;
65
66 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
67 context, "VertexBuffer");
68 auto vertex_buffer_count =
69 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
70 "VertexCount");
71
72 auto callback = [&](RenderPass& pass) -> bool {
73 ::memset(vertex_buffer_count->OnGetContents(), 0,
74 sizeof(SS::VertexBufferCount));
75 ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));
76 const auto* main_viewport = ImGui::GetMainViewport();
77 ImGui::SetNextWindowPos(
78 ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20));
79 ImGui::Begin("Path data", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
80 ImGui::InputTextMultiline("Path", svg_path_data,
81 IM_ARRAYSIZE(svg_path_data));
82 ImGui::DragFloat("Stroke width", &stroke_width, .1, 0.0, 25.0);
83
84 SkPath sk_path;
85 if (SkParsePath::FromSVGString(svg_path_data, &sk_path)) {
86 std::promise<bool> promise;
87 auto future = promise.get_future();
88
89 auto path = skia_conversions::ToPath(sk_path);
90 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
91 auto status =
94 .Tessellate(path, *host_buffer, context,
95 DeviceBuffer::AsBufferView(vertex_buffer),
96 DeviceBuffer::AsBufferView(vertex_buffer_count),
97 [vertex_buffer_count, &vertex_count,
98 &promise](CommandBuffer::Status status) {
99 vertex_count =
100 reinterpret_cast<SS::VertexBufferCount*>(
101 vertex_buffer_count->OnGetContents())
102 ->count;
103 promise.set_value(
104 status == CommandBuffer::Status::kCompleted);
105 });
106 switch (status) {
107 case ComputeTessellator::Status::kCommandInvalid:
108 ImGui::Text("Failed to submit compute job (invalid command)");
109 break;
110 case ComputeTessellator::Status::kTooManyComponents:
111 ImGui::Text("Failed to submit compute job (too many components) ");
112 break;
113 case ComputeTessellator::Status::kOk:
114 break;
115 }
116 if (!future.get()) {
117 ImGui::Text("Failed to submit compute job.");
118 return false;
119 }
120 if (vertex_count > 0) {
121 ImGui::Text("Vertex count: %zu", vertex_count);
122 }
123 } else {
124 ImGui::Text("Failed to parse path data");
125 }
126 ImGui::End();
127
128 ContentContext renderer(context, nullptr);
129 if (!renderer.IsValid()) {
130 return false;
131 }
132
133 using VS = SolidFillPipeline::VertexShader;
134
135 pass.SetCommandLabel("Draw Stroke");
136 pass.SetStencilReference(0);
137
138 ContentContextOptions options;
139 options.sample_count = pass.GetRenderTarget().GetSampleCount();
140 options.color_attachment_pixel_format =
141 pass.GetRenderTarget().GetRenderTargetPixelFormat();
142 options.has_depth_stencil_attachments =
143 pass.GetRenderTarget().GetStencilAttachment().has_value();
144 options.blend_mode = BlendMode::kSourceIn;
145 options.primitive_type = PrimitiveType::kTriangleStrip;
146
147 options.stencil_mode =
148 ContentContextOptions::StencilMode::kOverdrawPreventionIncrement;
149
150 pass.SetPipeline(renderer.GetSolidFillPipeline(options));
151
152 auto count = reinterpret_cast<SS::VertexBufferCount*>(
153 vertex_buffer_count->OnGetContents())
154 ->count;
155
156 pass.SetVertexBuffer(
157 VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
158 .vertex_count = count,
159 .index_type = IndexType::kNone});
160
161 VS::FrameInfo frame_info;
162 auto world_matrix = Matrix::MakeScale(GetContentScale());
163 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
164 frame_info.color = Color::Red().Premultiply();
165 VS::BindFrameInfo(
166 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
167
168 return pass.Draw().ok();
169 };
170 ASSERT_TRUE(OpenPlaygroundHere(callback));
171}
static bool FromSVGString(const char str[], SkPath *)
A utility that generates triangles of the specified fill type given a path.
ComputeTessellator & SetStrokeWidth(Scalar value)
Status Tessellate(const Path &path, HostBuffer &host_buffer, const std::shared_ptr< Context > &context, BufferView vertex_buffer, BufferView vertex_buffer_count, const CommandBuffer::CompletionCallback &callback=nullptr) const
Generates triangles from the path. If the data needs to be synchronized back to the CPU,...
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition render_pass.h:33

◆ TEST_P() [228/435]

impeller::testing::TEST_P ( ComputeSubgroupTest  ,
QuadAndCubicInOnePath   
)

Definition at line 371 of file compute_subgroup_unittests.cc.

371 {
372 using SS = StrokeComputeShader;
373
374 auto context = GetContext();
375 ASSERT_TRUE(context);
376 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
377
378 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
379 context, "VertexBuffer");
380 auto vertex_buffer_count =
381 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
382 "VertexBufferCount");
383
384 auto path = PathBuilder{}
385 .AddCubicCurve({140, 20}, {73, 20}, {20, 74}, {20, 140})
386 .AddQuadraticCurve({20, 140}, {93, 90}, {100, 42})
387 .TakePath();
388
389 auto tessellator = ComputeTessellator{};
390
392
393 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
394 auto status = tessellator.Tessellate(
395 path, *host_buffer, context, DeviceBuffer::AsBufferView(vertex_buffer),
396 DeviceBuffer::AsBufferView(vertex_buffer_count),
397 [&latch](CommandBuffer::Status status) {
398 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
399 latch.Signal();
400 });
401
402 ASSERT_EQ(status, ComputeTessellator::Status::kOk);
403
404 auto callback = [&](RenderPass& pass) -> bool {
405 ContentContext renderer(context, nullptr);
406 if (!renderer.IsValid()) {
407 return false;
408 }
409
410 using VS = SolidFillPipeline::VertexShader;
411
412 pass.SetCommandLabel("Draw Stroke");
413 pass.SetStencilReference(0);
414
415 ContentContextOptions options;
416 options.sample_count = pass.GetRenderTarget().GetSampleCount();
417 options.color_attachment_pixel_format =
418 pass.GetRenderTarget().GetRenderTargetPixelFormat();
419 options.has_depth_stencil_attachments =
420 pass.GetRenderTarget().GetStencilAttachment().has_value();
421 options.blend_mode = BlendMode::kSourceIn;
422 options.primitive_type = PrimitiveType::kTriangleStrip;
423
424 options.stencil_mode =
425 ContentContextOptions::StencilMode::kOverdrawPreventionIncrement;
426
427 pass.SetPipeline(renderer.GetSolidFillPipeline(options));
428
429 auto count = reinterpret_cast<SS::VertexBufferCount*>(
430 vertex_buffer_count->OnGetContents())
431 ->count;
432
433 pass.SetVertexBuffer(
434 VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
435 .vertex_count = count,
436 .index_type = IndexType::kNone});
437
438 VS::FrameInfo frame_info;
439 auto world_matrix = Matrix::MakeScale(GetContentScale());
440 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
441 frame_info.color = Color::Red().Premultiply();
442 VS::BindFrameInfo(
443 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
444
445 return pass.Draw().ok();
446 };
447 ASSERT_TRUE(OpenPlaygroundHere(callback));
448
449 // The latch is down here because it's expected that on Metal the backend
450 // will take care of synchronizing the buffer between the compute and render
451 // pass usages, since it's not MTLHeap allocated. However, if playgrounds
452 // are disabled, no render pass actually gets submitted and we need to do a
453 // CPU latch here.
454 latch.Wait();
455
456 auto vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
457 vertex_buffer_count->OnGetContents())
458 ->count;
459 EXPECT_EQ(vertex_count, golden_cubic_and_quad_points.size());
460 auto vertex_buffer_data =
461 reinterpret_cast<SS::VertexBuffer<2048>*>(vertex_buffer->OnGetContents());
462 for (size_t i = 0; i < vertex_count; i++) {
463 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].x -
464 vertex_buffer_data->position[i].x),
465 1e-3);
466 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].y -
467 vertex_buffer_data->position[i].y),
468 1e-3);
469 }
470}
PathBuilder & AddCubicCurve(Point p1, Point cp1, Point cp2, Point p2)
Move to point p1, then insert a cubic curve from p1 to p2 with control points cp1 and cp2.
std::vector< Point > golden_cubic_and_quad_points

◆ TEST_P() [229/435]

impeller::testing::TEST_P ( ComputeTest  ,
1DThreadgroupSizingIsCorrect   
)

Definition at line 175 of file compute_unittests.cc.

175 {
176 using CS = ThreadgroupSizingTestComputeShader;
177 auto context = GetContext();
178 ASSERT_TRUE(context);
179 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
180
181 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
182 auto pipeline_desc =
183 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
184 ASSERT_TRUE(pipeline_desc.has_value());
185 auto compute_pipeline =
186 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
187 ASSERT_TRUE(compute_pipeline);
188
189 auto cmd_buffer = context->CreateCommandBuffer();
190 auto pass = cmd_buffer->CreateComputePass();
191 ASSERT_TRUE(pass && pass->IsValid());
192
193 static constexpr size_t kCount = 2048;
194
195 pass->SetPipeline(compute_pipeline);
196
197 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
198 context, "Output Buffer");
199
200 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
201
202 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
203 ASSERT_TRUE(pass->EncodeCommands());
204
206 ASSERT_TRUE(
207 context->GetCommandQueue()
208 ->Submit({cmd_buffer},
209 [&latch, output_buffer](CommandBuffer::Status status) {
210 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
211
212 auto view = DeviceBuffer::AsBufferView(output_buffer);
213 EXPECT_EQ(view.range.length,
214 sizeof(CS::OutputData<kCount>));
215
216 CS::OutputData<kCount>* output =
217 reinterpret_cast<CS::OutputData<kCount>*>(
218 output_buffer->OnGetContents());
219 EXPECT_TRUE(output);
220 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
221 latch.Signal();
222 })
223 .ok());
224
225 latch.Wait();
226}
An optional (but highly recommended) utility for creating pipelines from reflected shader information...

◆ TEST_P() [230/435]

impeller::testing::TEST_P ( ComputeTest  ,
CanCompute1DimensionalData   
)

Definition at line 373 of file compute_unittests.cc.

373 {
374 using CS = SampleComputeShader;
375 auto context = GetContext();
376 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
377 ASSERT_TRUE(context);
378 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
379
380 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
381 auto pipeline_desc =
382 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
383 ASSERT_TRUE(pipeline_desc.has_value());
384 auto compute_pipeline =
385 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
386 ASSERT_TRUE(compute_pipeline);
387
388 auto cmd_buffer = context->CreateCommandBuffer();
389 auto pass = cmd_buffer->CreateComputePass();
390 ASSERT_TRUE(pass && pass->IsValid());
391
392 static constexpr size_t kCount = 5;
393
394 pass->SetPipeline(compute_pipeline);
395
396 CS::Info info{.count = kCount};
397 CS::Input0<kCount> input_0;
398 CS::Input1<kCount> input_1;
399 for (size_t i = 0; i < kCount; i++) {
400 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
401 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
402 }
403
404 input_0.fixed_array[1] = IPoint32(2, 2);
405 input_1.fixed_array[0] = UintPoint32(3, 3);
406 input_0.some_int = 5;
407 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
408
409 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
410 context, "Output Buffer");
411
412 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
413 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
414 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
415 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
416
417 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
418 ASSERT_TRUE(pass->EncodeCommands());
419
421 ASSERT_TRUE(
422 context->GetCommandQueue()
423 ->Submit(
424 {cmd_buffer},
425 [&latch, output_buffer, &input_0,
426 &input_1](CommandBuffer::Status status) {
427 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
428
429 auto view = DeviceBuffer::AsBufferView(output_buffer);
430 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
431
432 CS::Output<kCount>* output =
433 reinterpret_cast<CS::Output<kCount>*>(
434 output_buffer->OnGetContents());
435 EXPECT_TRUE(output);
436 for (size_t i = 0; i < kCount; i++) {
437 Vector4 vector = output->elements[i];
438 Vector4 computed = input_0.elements[i] * input_1.elements[i];
439 EXPECT_EQ(vector,
440 Vector4(computed.x + 2 + input_1.some_struct.i,
441 computed.y + 3 + input_1.some_struct.vf.x,
442 computed.z + 5 + input_1.some_struct.vf.y,
443 computed.w));
444 }
445 latch.Signal();
446 })
447 .ok());
448
449 latch.Wait();
450}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213

◆ TEST_P() [231/435]

impeller::testing::TEST_P ( ComputeTest  ,
CanComputePrefixSum   
)

Definition at line 109 of file compute_unittests.cc.

109 {
110 using CS = PrefixSumTestComputeShader;
111 auto context = GetContext();
112 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
113 ASSERT_TRUE(context);
114 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
115
116 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
117 auto pipeline_desc =
118 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
119 ASSERT_TRUE(pipeline_desc.has_value());
120 auto compute_pipeline =
121 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
122 ASSERT_TRUE(compute_pipeline);
123
124 auto cmd_buffer = context->CreateCommandBuffer();
125 auto pass = cmd_buffer->CreateComputePass();
126 ASSERT_TRUE(pass && pass->IsValid());
127
128 static constexpr size_t kCount = 5;
129
130 pass->SetPipeline(compute_pipeline);
131
132 CS::InputData<kCount> input_data;
133 input_data.count = kCount;
134 for (size_t i = 0; i < kCount; i++) {
135 input_data.data[i] = 1 + i;
136 }
137
138 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
139 context, "Output Buffer");
140
141 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
142 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
143
144 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
145 ASSERT_TRUE(pass->EncodeCommands());
146
148 ASSERT_TRUE(
149 context->GetCommandQueue()
150 ->Submit({cmd_buffer},
151 [&latch, output_buffer](CommandBuffer::Status status) {
152 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
153
154 auto view = DeviceBuffer::AsBufferView(output_buffer);
155 EXPECT_EQ(view.range.length,
156 sizeof(CS::OutputData<kCount>));
157
158 CS::OutputData<kCount>* output =
159 reinterpret_cast<CS::OutputData<kCount>*>(
160 output_buffer->OnGetContents());
161 EXPECT_TRUE(output);
162
163 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
164 for (size_t i = 0; i < kCount; i++) {
165 auto computed_sum = output->data[i];
166 EXPECT_EQ(computed_sum, expected[i]);
167 }
168 latch.Signal();
169 })
170 .ok());
171
172 latch.Wait();
173}

◆ TEST_P() [232/435]

impeller::testing::TEST_P ( ComputeTest  ,
CanComputePrefixSumLargeInteractive   
)

Definition at line 228 of file compute_unittests.cc.

228 {
229 using CS = PrefixSumTestComputeShader;
230
231 auto context = GetContext();
232 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
233
234 ASSERT_TRUE(context);
235 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
236
237 auto callback = [&](RenderPass& render_pass) -> bool {
238 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
239 auto pipeline_desc =
240 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
241 auto compute_pipeline =
242 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
243
244 auto cmd_buffer = context->CreateCommandBuffer();
245 auto pass = cmd_buffer->CreateComputePass();
246
247 static constexpr size_t kCount = 1023;
248
249 pass->SetPipeline(compute_pipeline);
250
251 CS::InputData<kCount> input_data;
252 input_data.count = kCount;
253 for (size_t i = 0; i < kCount; i++) {
254 input_data.data[i] = 1 + i;
255 }
256
257 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
258 context, "Output Buffer");
259
260 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
261 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
262
263 pass->Compute(ISize(kCount, 1));
264 pass->EncodeCommands();
265 host_buffer->Reset();
266 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
267 };
268 ASSERT_TRUE(OpenPlaygroundHere(callback));
269}

◆ TEST_P() [233/435]

impeller::testing::TEST_P ( ComputeTest  ,
CanCreateComputePass   
)

Definition at line 30 of file compute_unittests.cc.

30 {
31 using CS = SampleComputeShader;
32 auto context = GetContext();
33 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
34 ASSERT_TRUE(context);
35 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
36
37 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
38 auto pipeline_desc =
39 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
40 ASSERT_TRUE(pipeline_desc.has_value());
41 auto compute_pipeline =
42 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
43 ASSERT_TRUE(compute_pipeline);
44
45 auto cmd_buffer = context->CreateCommandBuffer();
46 auto pass = cmd_buffer->CreateComputePass();
47 ASSERT_TRUE(pass && pass->IsValid());
48
49 static constexpr size_t kCount = 5;
50
51 pass->SetPipeline(compute_pipeline);
52
53 CS::Info info{.count = kCount};
54 CS::Input0<kCount> input_0;
55 CS::Input1<kCount> input_1;
56 for (size_t i = 0; i < kCount; i++) {
57 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
58 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
59 }
60
61 input_0.fixed_array[1] = IPoint32(2, 2);
62 input_1.fixed_array[0] = UintPoint32(3, 3);
63 input_0.some_int = 5;
64 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
65
66 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
67 context, "Output Buffer");
68
69 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
70 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
71 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
72 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
73
74 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
75 ASSERT_TRUE(pass->EncodeCommands());
76
78 ASSERT_TRUE(
79 context->GetCommandQueue()
80 ->Submit(
81 {cmd_buffer},
82 [&latch, output_buffer, &input_0,
83 &input_1](CommandBuffer::Status status) {
84 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
85
86 auto view = DeviceBuffer::AsBufferView(output_buffer);
87 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
88
89 CS::Output<kCount>* output =
90 reinterpret_cast<CS::Output<kCount>*>(
91 output_buffer->OnGetContents());
92 EXPECT_TRUE(output);
93 for (size_t i = 0; i < kCount; i++) {
94 Vector4 vector = output->elements[i];
95 Vector4 computed = input_0.elements[i] * input_1.elements[i];
96 EXPECT_EQ(vector,
97 Vector4(computed.x + 2 + input_1.some_struct.i,
98 computed.y + 3 + input_1.some_struct.vf.x,
99 computed.z + 5 + input_1.some_struct.vf.y,
100 computed.w));
101 }
102 latch.Signal();
103 })
104 .ok());
105
106 latch.Wait();
107}

◆ TEST_P() [234/435]

impeller::testing::TEST_P ( ComputeTest  ,
CapabilitiesReportSupport   
)

Definition at line 24 of file compute_unittests.cc.

24 {
25 auto context = GetContext();
26 ASSERT_TRUE(context);
27 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
28}

◆ TEST_P() [235/435]

impeller::testing::TEST_P ( ComputeTest  ,
MultiStageInputAndOutput   
)

Definition at line 271 of file compute_unittests.cc.

271 {
272 using CS1 = Stage1ComputeShader;
273 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
274 using CS2 = Stage2ComputeShader;
275 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
276
277 auto context = GetContext();
278 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
279 ASSERT_TRUE(context);
280 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
281
282 auto pipeline_desc_1 =
283 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
284 ASSERT_TRUE(pipeline_desc_1.has_value());
285 auto compute_pipeline_1 =
286 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
287 ASSERT_TRUE(compute_pipeline_1);
288
289 auto pipeline_desc_2 =
290 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
291 ASSERT_TRUE(pipeline_desc_2.has_value());
292 auto compute_pipeline_2 =
293 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
294 ASSERT_TRUE(compute_pipeline_2);
295
296 auto cmd_buffer = context->CreateCommandBuffer();
297 auto pass = cmd_buffer->CreateComputePass();
298 ASSERT_TRUE(pass && pass->IsValid());
299
300 static constexpr size_t kCount1 = 5;
301 static constexpr size_t kCount2 = kCount1 * 2;
302
303 CS1::Input<kCount1> input_1;
304 input_1.count = kCount1;
305 for (size_t i = 0; i < kCount1; i++) {
306 input_1.elements[i] = i;
307 }
308
309 CS2::Input<kCount2> input_2;
310 input_2.count = kCount2;
311 for (size_t i = 0; i < kCount2; i++) {
312 input_2.elements[i] = i;
313 }
314
315 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
316 context, "Output Buffer Stage 1");
317 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
318 context, "Output Buffer Stage 2");
319
320 {
321 pass->SetPipeline(compute_pipeline_1);
322
323 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
324 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
325
326 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
327 pass->AddBufferMemoryBarrier();
328 }
329
330 {
331 pass->SetPipeline(compute_pipeline_2);
332
333 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
334 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
335 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
336 }
337
338 ASSERT_TRUE(pass->EncodeCommands());
339
341 ASSERT_TRUE(
342 context->GetCommandQueue()
343 ->Submit({cmd_buffer},
344 [&latch, &output_buffer_1,
345 &output_buffer_2](CommandBuffer::Status status) {
346 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
347
348 CS1::Output<kCount2>* output_1 =
349 reinterpret_cast<CS1::Output<kCount2>*>(
350 output_buffer_1->OnGetContents());
351 EXPECT_TRUE(output_1);
352 EXPECT_EQ(output_1->count, 10u);
353 EXPECT_THAT(
354 output_1->elements,
355 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
356
357 CS2::Output<kCount2>* output_2 =
358 reinterpret_cast<CS2::Output<kCount2>*>(
359 output_buffer_2->OnGetContents());
360 EXPECT_TRUE(output_2);
361 EXPECT_EQ(output_2->count, 10u);
362 EXPECT_THAT(output_2->elements,
363 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
364 18, 16, 24));
365
366 latch.Signal();
367 })
368 .ok());
369
370 latch.Wait();
371}

◆ TEST_P() [236/435]

impeller::testing::TEST_P ( ComputeTest  ,
ReturnsEarlyWhenAnyGridDimensionIsZero   
)

Definition at line 452 of file compute_unittests.cc.

452 {
453 using CS = SampleComputeShader;
454 auto context = GetContext();
455 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
456 ASSERT_TRUE(context);
457 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
458
459 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
460 auto pipeline_desc =
461 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
462 ASSERT_TRUE(pipeline_desc.has_value());
463 auto compute_pipeline =
464 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
465 ASSERT_TRUE(compute_pipeline);
466
467 auto cmd_buffer = context->CreateCommandBuffer();
468 auto pass = cmd_buffer->CreateComputePass();
469 ASSERT_TRUE(pass && pass->IsValid());
470
471 static constexpr size_t kCount = 5;
472
473 pass->SetPipeline(compute_pipeline);
474
475 CS::Info info{.count = kCount};
476 CS::Input0<kCount> input_0;
477 CS::Input1<kCount> input_1;
478 for (size_t i = 0; i < kCount; i++) {
479 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
480 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
481 }
482
483 input_0.fixed_array[1] = IPoint32(2, 2);
484 input_1.fixed_array[0] = UintPoint32(3, 3);
485 input_0.some_int = 5;
486 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
487
488 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
489 context, "Output Buffer");
490
491 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
492 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
493 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
494 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
495
496 // Intentionally making the grid size zero in one dimension. No GPU will
497 // tolerate this.
498 EXPECT_FALSE(pass->Compute(ISize(0, 1)).ok());
499 pass->EncodeCommands();
500}

◆ TEST_P() [237/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanBlendDstOverAndDstCorrectly   
)

Definition at line 1266 of file dl_unittests.cc.

1266 {
1268
1269 {
1270 builder.SaveLayer(nullptr, nullptr);
1271 builder.Translate(100, 100);
1273 paint.setColor(flutter::DlColor::kRed());
1274 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1275 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1277 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1278 builder.Restore();
1279 }
1280 {
1281 builder.SaveLayer(nullptr, nullptr);
1282 builder.Translate(300, 100);
1284 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1285 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1286 paint.setColor(flutter::DlColor::kRed());
1288 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1289 builder.Restore();
1290 }
1291 {
1292 builder.SaveLayer(nullptr, nullptr);
1293 builder.Translate(100, 300);
1295 paint.setColor(flutter::DlColor::kRed());
1296 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1297 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1298 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1299 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1300 builder.Restore();
1301 }
1302 {
1303 builder.SaveLayer(nullptr, nullptr);
1304 builder.Translate(300, 300);
1306 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1307 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1308 paint.setColor(flutter::DlColor::kRed());
1309 paint.setBlendMode(flutter::DlBlendMode::kDst);
1310 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1311 builder.Restore();
1312 }
1313
1314 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1315}
@ kSrcOver
r = s + (1-sa)*d
@ kDstOver
r = d + (1-da)*s
static constexpr SkRect MakeSize(const SkSize &size)
Definition SkRect.h:633

◆ TEST_P() [238/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanClampTheResultingColorOfColorMatrixFilter   
)

Definition at line 616 of file dl_unittests.cc.

616 {
617 auto texture = CreateTextureForFixture("boston.jpg");
618 const float inner_color_matrix[20] = {
619 1, 0, 0, 0, 0, //
620 0, 1, 0, 0, 0, //
621 0, 0, 1, 0, 0, //
622 0, 0, 0, 2, 0, //
623 };
624 const float outer_color_matrix[20] = {
625 1, 0, 0, 0, 0, //
626 0, 1, 0, 0, 0, //
627 0, 0, 1, 0, 0, //
628 0, 0, 0, 0.5, 0, //
629 };
630 auto inner_color_filter =
631 std::make_shared<flutter::DlMatrixColorFilter>(inner_color_matrix);
632 auto outer_color_filter =
633 std::make_shared<flutter::DlMatrixColorFilter>(outer_color_matrix);
634 auto inner =
635 std::make_shared<flutter::DlColorFilterImageFilter>(inner_color_filter);
636 auto outer =
637 std::make_shared<flutter::DlColorFilterImageFilter>(outer_color_filter);
638 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
639
642 paint.setImageFilter(compose.get());
643 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
645 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
646}

◆ TEST_P() [239/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanConvertTriangleFanToTriangles   
)

Definition at line 977 of file dl_unittests.cc.

977 {
978 constexpr Scalar hexagon_radius = 125;
979 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
980 auto center_to_flat = 1.73 / 2 * hexagon_radius;
981
982 // clang-format off
983 std::vector<SkPoint> vertices = {
984 SkPoint::Make(hex_start.x, hex_start.y),
985 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
986 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
987 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
988 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
989 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
990 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
991 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
992 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
993 };
994 // clang-format on
996 auto dl_vertices = flutter::DlVertices::Make(
997 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
998 nullptr, nullptr);
1000 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
1001 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1002}
static std::shared_ptr< DlVertices > Make(DlVertexMode mode, int vertex_count, const SkPoint vertices[], const SkPoint texture_coordinates[], const DlColor colors[], int index_count=0, const uint16_t indices[]=nullptr)
Constructs a DlVector with compact inline storage for all of its required and optional lists of data.
static constexpr DlColor kDarkGrey()
Definition dl_color.h:30

◆ TEST_P() [240/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawAnOpenPath   
)

Definition at line 406 of file dl_unittests.cc.

406 {
409
410 paint.setColor(flutter::DlColor::kRed());
412 paint.setStrokeWidth(10);
413
414 builder.Translate(300, 300);
415
416 // Move to (50, 50) and draw lines from:
417 // 1. (50, height)
418 // 2. (width, height)
419 // 3. (width, 50)
420 SkPath path;
421 path.moveTo(50, 50);
422 path.lineTo(50, 100);
423 path.lineTo(100, 100);
424 path.lineTo(100, 50);
425 builder.DrawPath(path, paint);
426
427 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
428}
@ kStroke
strokes boundary of shapes

◆ TEST_P() [241/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawArc   
)

Definition at line 152 of file dl_unittests.cc.

152 {
153 auto callback = [&]() {
154 static float start_angle = 45;
155 static float sweep_angle = 270;
156 static float stroke_width = 10;
157 static bool use_center = true;
158
159 static int selected_cap = 0;
160 const char* cap_names[] = {"Butt", "Round", "Square"};
162
163 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
164 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
165 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
166 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
167 ImGui::Combo("Cap", &selected_cap, cap_names,
168 sizeof(cap_names) / sizeof(char*));
169 ImGui::Checkbox("Use center", &use_center);
170 ImGui::End();
171
172 switch (selected_cap) {
173 case 0:
175 break;
176 case 1:
178 break;
179 case 2:
181 break;
182 default:
184 break;
185 }
186
187 static PlaygroundPoint point_a(Point(200, 200), 20, Color::White());
188 static PlaygroundPoint point_b(Point(400, 400), 20, Color::White());
189 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
190
193
194 Vector2 scale = GetContentScale();
195 builder.Scale(scale.x, scale.y);
197 paint.setStrokeCap(cap);
199 paint.setStrokeMiter(10);
200 auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
202 paint.setStrokeWidth(2);
203 builder.DrawRect(rect, paint);
204 paint.setColor(flutter::DlColor::kRed());
205 paint.setStrokeWidth(stroke_width);
206 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
207
208 return builder.Build();
209 };
210 ASSERT_TRUE(OpenPlaygroundHere(callback));
211}
@ kMiter
extends to miter limit
DlStrokeCap
Definition dl_paint.h:29
@ kRound
adds circle
@ kButt
no stroke extension
@ kSquare
adds square

◆ TEST_P() [242/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawBackdropFilter   
)

Definition at line 648 of file dl_unittests.cc.

648 {
649 auto texture = CreateTextureForFixture("embarcadero.jpg");
650
651 auto callback = [&]() {
652 static float sigma[] = {10, 10};
653 static float ctm_scale = 1;
654 static bool use_bounds = true;
655 static bool draw_circle = true;
656 static bool add_clip = true;
657
658 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
659 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
660 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
661 ImGui::NewLine();
662 ImGui::TextWrapped(
663 "If everything is working correctly, none of the options below should "
664 "impact the filter's appearance.");
665 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
666 ImGui::Checkbox("Draw child element", &draw_circle);
667 ImGui::Checkbox("Add pre-clip", &add_clip);
668 ImGui::End();
669
671
672 Vector2 scale = ctm_scale * GetContentScale();
673 builder.Scale(scale.x, scale.y);
674
675 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
677
678 std::optional<SkRect> bounds;
679 if (use_bounds) {
680 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
681 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
682 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
683 bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
684 }
685
686 // Insert a clip to test that the backdrop filter handles stencil depths > 0
687 // correctly.
688 if (add_clip) {
689 builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
691 }
692
693 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
695 builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
696 &filter);
697
698 if (draw_circle) {
699 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
700 auto circle_center = DrawPlaygroundPoint(center_point);
701
706 paint.setStrokeWidth(10);
707 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
708 builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint);
709 }
710
711 return builder.Build();
712 };
713
714 ASSERT_TRUE(OpenPlaygroundHere(callback));
715}
@ kBevel
connects outside edges

◆ TEST_P() [243/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawCapsAndJoins   
)

Definition at line 106 of file dl_unittests.cc.

106 {
109
111 paint.setStrokeWidth(30);
112 paint.setColor(flutter::DlColor::kRed());
113
114 auto path =
115 SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot();
116
117 builder.Translate(100, 100);
118 {
121 paint.setStrokeMiter(4);
122 builder.DrawPath(path, paint);
123 }
124
125 {
126 builder.Save();
127 builder.Translate(0, 100);
128 // The joint in the path is 45 degrees. A miter length of 1 convert to a
129 // bevel in this case.
130 paint.setStrokeMiter(1);
131 builder.DrawPath(path, paint);
132 builder.Restore();
133 }
134
135 builder.Translate(150, 0);
136 {
139 builder.DrawPath(path, paint);
140 }
141
142 builder.Translate(150, 0);
143 {
146 builder.DrawPath(path, paint);
147 }
148
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150}
SkPathBuilder & lineTo(SkPoint pt)
SkPathBuilder & moveTo(SkPoint pt)
SkPath snapshot() const

◆ TEST_P() [244/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawCorrectlyWithColorFilterAndImageFilter   
)

Definition at line 1317 of file dl_unittests.cc.

1317 {
1319 const float green_color_matrix[20] = {
1320 0, 0, 0, 0, 0, //
1321 0, 0, 0, 0, 1, //
1322 0, 0, 0, 0, 0, //
1323 0, 0, 0, 1, 0, //
1324 };
1325 const float blue_color_matrix[20] = {
1326 0, 0, 0, 0, 0, //
1327 0, 0, 0, 0, 0, //
1328 0, 0, 0, 0, 1, //
1329 0, 0, 0, 1, 0, //
1330 };
1331 auto green_color_filter =
1332 std::make_shared<flutter::DlMatrixColorFilter>(green_color_matrix);
1333 auto blue_color_filter =
1334 std::make_shared<flutter::DlMatrixColorFilter>(blue_color_matrix);
1335 auto blue_image_filter =
1336 std::make_shared<flutter::DlColorFilterImageFilter>(blue_color_filter);
1337
1339 paint.setColor(flutter::DlColor::kRed());
1340 paint.setColorFilter(green_color_filter);
1341 paint.setImageFilter(blue_image_filter);
1342 builder.DrawRect(SkRect::MakeLTRB(100, 100, 500, 500), paint);
1343 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1344}

◆ TEST_P() [245/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawImage   
)

Definition at line 98 of file dl_unittests.cc.

98 {
99 auto texture = CreateTextureForFixture("embarcadero.jpg");
101 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
103 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
104}

◆ TEST_P() [246/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawNinePatchImage   
)

Definition at line 717 of file dl_unittests.cc.

717 {
718 // Image is drawn with corners to scale and center pieces stretched to fit.
719 auto texture = CreateTextureForFixture("embarcadero.jpg");
721 auto size = texture->GetSize();
722 builder.DrawImageNine(
723 DlImageImpeller::Make(texture),
724 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
725 size.height * 3 / 4),
726 SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
728 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
729}
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition SkRect.h:91

◆ TEST_P() [247/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawNinePatchImageCenterBiggerThanDest   
)

Definition at line 763 of file dl_unittests.cc.

763 {
764 // Edge case, the width and height of the corners does not leave any
765 // room for the center slices. Only the corners are displayed.
766 auto texture = CreateTextureForFixture("embarcadero.jpg");
768 auto size = texture->GetSize();
769 builder.DrawImageNine(
770 DlImageImpeller::Make(texture),
771 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
772 size.height * 3 / 4),
773 SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
775 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
776}

◆ TEST_P() [248/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawNinePatchImageCenterHeightBiggerThanDest   
)

Definition at line 747 of file dl_unittests.cc.

747 {
748 // Edge case, the height of the corners does not leave any room for the
749 // center slice. The center (across the horizontal axis) is folded out of the
750 // resulting image.
751 auto texture = CreateTextureForFixture("embarcadero.jpg");
753 auto size = texture->GetSize();
754 builder.DrawImageNine(
755 DlImageImpeller::Make(texture),
756 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
757 size.height * 3 / 4),
758 SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
760 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
761}

◆ TEST_P() [249/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawNinePatchImageCenterWidthBiggerThanDest   
)

Definition at line 731 of file dl_unittests.cc.

731 {
732 // Edge case, the width of the corners does not leave any room for the
733 // center slice. The center (across the vertical axis) is folded out of the
734 // resulting image.
735 auto texture = CreateTextureForFixture("embarcadero.jpg");
737 auto size = texture->GetSize();
738 builder.DrawImageNine(
739 DlImageImpeller::Make(texture),
740 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
741 size.height * 3 / 4),
742 SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
744 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
745}

◆ TEST_P() [250/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawNinePatchImageCornersScaledDown   
)

Definition at line 778 of file dl_unittests.cc.

778 {
779 // Edge case, there is not enough room for the corners to be drawn
780 // without scaling them down.
781 auto texture = CreateTextureForFixture("embarcadero.jpg");
783 auto size = texture->GetSize();
784 builder.DrawImageNine(
785 DlImageImpeller::Make(texture),
786 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
787 size.height * 3 / 4),
788 SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
790 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
791}

◆ TEST_P() [251/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawPaintWithColorSource   
)

Definition at line 1214 of file dl_unittests.cc.

1214 {
1215 const flutter::DlColor colors[2] = {
1216 flutter::DlColor(0xFFF44336),
1217 flutter::DlColor(0xFF2196F3),
1218 };
1219 const float stops[2] = {0.0, 1.0};
1222 auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
1223 builder.Save();
1224 builder.Translate(100, 100);
1225 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1226 auto linear =
1227 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1229 paint.setColorSource(linear);
1230 builder.DrawPaint(paint);
1231 builder.Restore();
1232
1233 builder.Save();
1234 builder.Translate(500, 100);
1235 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1237 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1238 paint.setColorSource(radial);
1239 builder.DrawPaint(paint);
1240 builder.Restore();
1241
1242 builder.Save();
1243 builder.Translate(100, 500);
1244 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1245 auto sweep =
1246 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1248 paint.setColorSource(sweep);
1249 builder.DrawPaint(paint);
1250 builder.Restore();
1251
1252 builder.Save();
1253 builder.Translate(500, 500);
1254 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1255 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1256 auto image = std::make_shared<flutter::DlImageColorSource>(
1257 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1259 paint.setColorSource(image);
1260 builder.DrawPaint(paint);
1261 builder.Restore();
1262
1263 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1264}
static std::shared_ptr< DlSweepGradientColorSource > MakeSweep(SkPoint center, SkScalar start, SkScalar end, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
static std::shared_ptr< DlRadialGradientColorSource > MakeRadial(SkPoint center, SkScalar radius, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609

◆ TEST_P() [252/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawPoints   
)

Definition at line 805 of file dl_unittests.cc.

805 {
807 SkPoint points[7] = {
808 {0, 0}, //
809 {100, 100}, //
810 {100, 0}, //
811 {0, 100}, //
812 {0, 0}, //
813 {48, 48}, //
814 {52, 52}, //
815 };
816 std::vector<flutter::DlStrokeCap> caps = {
820 };
823 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
824 .setStrokeWidth(20);
825 builder.Translate(50, 50);
826 for (auto cap : caps) {
827 paint.setStrokeCap(cap);
828 builder.Save();
830 builder.Translate(150, 0);
832 builder.Translate(150, 0);
834 paint);
835 builder.Restore();
836 builder.Translate(0, 150);
837 }
838 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
839}
@ kLines
draw each separate pair of points as a line segment
@ kPolygon
draw each pair of overlapping points as a line segment
@ kPoints
draw each point separately
DlPaint & setColor(DlColor color)
Definition dl_paint.h:71
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:117
static constexpr DlColor kYellow()
Definition dl_color.h:29

◆ TEST_P() [253/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawRect   
)

Definition at line 49 of file dl_unittests.cc.

49 {
51 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),
53 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
54}
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659

◆ TEST_P() [254/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawRectWithLinearToSrgbColorFilter   
)

Definition at line 1198 of file dl_unittests.cc.

1198 {
1200 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1202 paint.setColorFilter(
1204 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1205 builder.Translate(0, 200);
1206
1207 paint.setColorFilter(
1209 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1210
1211 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1212}
static const std::shared_ptr< DlLinearToSrgbGammaColorFilter > kInstance
static const std::shared_ptr< DlSrgbToLinearGammaColorFilter > kInstance

◆ TEST_P() [255/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawShadow   
)

Definition at line 864 of file dl_unittests.cc.

864 {
867
868 auto content_scale = GetContentScale() * 0.8;
869 builder.Scale(content_scale.x, content_scale.y);
870
871 constexpr size_t star_spikes = 5;
872 constexpr SkScalar half_spike_rotation = kPi / star_spikes;
873 constexpr SkScalar radius = 40;
874 constexpr SkScalar spike_size = 10;
875 constexpr SkScalar outer_radius = radius + spike_size;
876 constexpr SkScalar inner_radius = radius - spike_size;
877 std::array<SkPoint, star_spikes * 2> star;
878 for (size_t i = 0; i < star_spikes; i++) {
879 const SkScalar rotation = half_spike_rotation * i * 2;
880 star[i * 2] = SkPoint::Make(50 + std::sin(rotation) * outer_radius,
881 50 - std::cos(rotation) * outer_radius);
882 star[i * 2 + 1] = SkPoint::Make(
883 50 + std::sin(rotation + half_spike_rotation) * inner_radius,
884 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
885 }
886
887 std::array<SkPath, 4> paths = {
888 SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
890 SkRRect::MakeRectXY(SkRect::MakeXYWH(20, 0, 200, 100), 30, 30)),
891 SkPath{}.addCircle(100, 50, 50),
892 SkPath{}.addPoly(star.data(), star.size(), true),
893 };
895 builder.DrawPaint(paint);
896 paint.setColor(flutter::DlColor::kCyan());
897 builder.Translate(100, 50);
898 for (size_t x = 0; x < paths.size(); x++) {
899 builder.Save();
900 for (size_t y = 0; y < 6; y++) {
901 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
902 1);
903 builder.DrawPath(paths[x], paint);
904 builder.Translate(0, 150);
905 }
906 builder.Restore();
907 builder.Translate(250, 0);
908 }
909
910 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
911}
SkPath & addPoly(const SkPoint pts[], int count, bool close)
Definition SkPath.cpp:880
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition SkPath.cpp:854
float SkScalar
Definition extension.cpp:12
static constexpr DlColor kWhite()
Definition dl_color.h:23
static constexpr DlColor kBlack()
Definition dl_color.h:22
static constexpr DlColor kCyan()
Definition dl_color.h:27

◆ TEST_P() [256/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawStrokedText   
)

Definition at line 466 of file dl_unittests.cc.

466 {
469
471 paint.setColor(flutter::DlColor::kRed());
472 builder.DrawTextBlob(
473 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
474 250, 250, paint);
475
476 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
477}

◆ TEST_P() [257/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawTextBlob   
)

Definition at line 56 of file dl_unittests.cc.

56 {
58 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
60 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
61}

◆ TEST_P() [258/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawTextBlobWithGradient   
)

Definition at line 63 of file dl_unittests.cc.

63 {
65
66 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
68 const float stops[2] = {0.0, 1.0};
69
70 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
71 2, colors.data(), stops,
74 paint.setColorSource(linear);
75
76 builder.DrawTextBlob(
77 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
78 paint);
79 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
80}

◆ TEST_P() [259/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawTextWithSaveLayer   
)

Definition at line 82 of file dl_unittests.cc.

82 {
84 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
86
87 flutter::DlPaint save_paint;
88 float alpha = 0.5;
89 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
90 builder.SaveLayer(nullptr, &save_paint);
91 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
92 CreateTestFontOfSize(100)),
94 builder.Restore();
95 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
96}
DlPaint & setAlpha(uint8_t alpha)
Definition dl_paint.h:77

◆ TEST_P() [260/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithBlendColorFilter   
)

Definition at line 518 of file dl_unittests.cc.

518 {
519 auto texture = CreateTextureForFixture("embarcadero.jpg");
522
523 // Pipeline blended image.
524 {
527 paint.setColorFilter(&filter);
528 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
530 }
531
532 // Advanced blended image.
533 {
536 paint.setColorFilter(&filter);
537 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
539 }
540
541 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
542}
@ kScreen
r = s + d - s*d

◆ TEST_P() [261/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithColorFilterImageFilter   
)

Definition at line 544 of file dl_unittests.cc.

544 {
545 const float invert_color_matrix[20] = {
546 -1, 0, 0, 0, 1, //
547 0, -1, 0, 0, 1, //
548 0, 0, -1, 0, 1, //
549 0, 0, 0, 1, 0, //
550 };
551 auto texture = CreateTextureForFixture("boston.jpg");
554
555 auto color_filter =
556 std::make_shared<flutter::DlMatrixColorFilter>(invert_color_matrix);
557 auto image_filter =
558 std::make_shared<flutter::DlColorFilterImageFilter>(color_filter);
559
560 paint.setImageFilter(image_filter.get());
561 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
563
564 builder.Translate(0, 700);
565 paint.setColorFilter(color_filter.get());
566 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
568 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
569}
static sk_sp< SkImage > color_filter(const SkImage *image, SkColorFilter *colorFilter)
T * get() const
Definition SkRefCnt.h:303

◆ TEST_P() [262/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithComposeImageFilter   
)

Definition at line 596 of file dl_unittests.cc.

596 {
597 auto texture = CreateTextureForFixture("boston.jpg");
600
601 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
602 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
603 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
604 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
605
606 paint.setImageFilter(open.get());
607 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
609 builder.Translate(0, 700);
610 paint.setImageFilter(close.get());
611 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
613 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
614}

◆ TEST_P() [263/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithImageBlurFilter   
)

Definition at line 571 of file dl_unittests.cc.

571 {
572 auto texture = CreateTextureForFixture("embarcadero.jpg");
573
574 auto callback = [&]() {
575 static float sigma[] = {10, 10};
576
577 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
578 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
579 ImGui::End();
580
583
584 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
586 paint.setImageFilter(&filter);
587 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
589
590 return builder.Build();
591 };
592
593 ASSERT_TRUE(OpenPlaygroundHere(callback));
594}

◆ TEST_P() [264/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithMaskBlur   
)

Definition at line 430 of file dl_unittests.cc.

430 {
431 auto texture = CreateTextureForFixture("embarcadero.jpg");
434
435 // Mask blurred image.
436 {
437 auto filter =
439 paint.setMaskFilter(&filter);
440 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
442 }
443
444 // Mask blurred filled path.
445 {
447 auto filter =
449 paint.setMaskFilter(&filter);
450 builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
451 }
452
453 // Mask blurred text.
454 {
455 auto filter =
457 paint.setMaskFilter(&filter);
458 builder.DrawTextBlob(
459 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
460 paint);
461 }
462
463 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
464}
@ kNormal
fuzzy inside and outside
@ kOuter
nothing inside, fuzzy outside
@ kSolid
solid inside, fuzzy outside

◆ TEST_P() [265/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithMatrixFilter   
)

Definition at line 1038 of file dl_unittests.cc.

1038 {
1039 auto boston = CreateTextureForFixture("boston.jpg");
1040
1041 auto callback = [&]() {
1042 static int selected_matrix_type = 0;
1043 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
1044
1045 static float ctm_translation[2] = {200, 200};
1046 static float ctm_scale[2] = {0.65, 0.65};
1047 static float ctm_skew[2] = {0, 0};
1048
1049 static bool enable = true;
1050 static float translation[2] = {100, 100};
1051 static float scale[2] = {0.8, 0.8};
1052 static float skew[2] = {0.2, 0.2};
1053
1054 static bool enable_savelayer = true;
1055
1056 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1057 {
1058 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
1059 sizeof(matrix_type_names) / sizeof(char*));
1060
1061 ImGui::TextWrapped("Current Transform");
1062 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
1063 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
1064 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
1065
1066 ImGui::TextWrapped(
1067 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
1068 "The only difference is that MatrixFilter doesn't affect the effect "
1069 "transform, whereas LocalMatrixFilter does.");
1070 // Note: See this behavior in:
1071 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
1072 ImGui::Checkbox("Enable", &enable);
1073 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
1074 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
1075 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
1076
1077 ImGui::TextWrapped(
1078 "Rendering the filtered image within a layer can expose bounds "
1079 "issues. If the rendered image gets cut off when this setting is "
1080 "enabled, there's a coverage bug in the filter.");
1081 ImGui::Checkbox("Render in layer", &enable_savelayer);
1082 }
1083 ImGui::End();
1084
1087
1088 if (enable_savelayer) {
1089 builder.SaveLayer(nullptr, nullptr);
1090 }
1091 {
1092 auto content_scale = GetContentScale();
1093 builder.Scale(content_scale.x, content_scale.y);
1094
1095 // Set the current transform
1096 auto ctm_matrix =
1097 SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
1098 ctm_skew[1], ctm_scale[1], ctm_translation[1], //
1099 0, 0, 1);
1100 builder.Transform(ctm_matrix);
1101
1102 // Set the matrix filter
1103 auto filter_matrix =
1104 SkMatrix::MakeAll(scale[0], skew[0], translation[0], //
1105 skew[1], scale[1], translation[1], //
1106 0, 0, 1);
1107
1108 if (enable) {
1109 switch (selected_matrix_type) {
1110 case 0: {
1111 auto filter = flutter::DlMatrixImageFilter(
1112 filter_matrix, flutter::DlImageSampling::kLinear);
1113 paint.setImageFilter(&filter);
1114 break;
1115 }
1116 case 1: {
1117 auto internal_filter =
1119 .shared();
1120 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1121 internal_filter);
1122 paint.setImageFilter(&filter);
1123 break;
1124 }
1125 }
1126 }
1127
1128 builder.DrawImage(DlImageImpeller::Make(boston), {},
1130 }
1131 if (enable_savelayer) {
1132 builder.Restore();
1133 }
1134
1135 return builder.Build();
1136 };
1137
1138 ASSERT_TRUE(OpenPlaygroundHere(callback));
1139}
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
Definition SkMatrix.h:179
std::shared_ptr< DlImageFilter > shared() const override

◆ TEST_P() [266/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithMatrixFilterWhenSavingLayer   
)

Definition at line 1141 of file dl_unittests.cc.

1141 {
1142 auto callback = [&]() {
1143 static float translation[2] = {0, 0};
1144 static bool enable_save_layer = true;
1145
1146 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1147 ImGui::SliderFloat2("Translation", translation, -130, 130);
1148 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1149 ImGui::End();
1150
1152 builder.Save();
1153 builder.Scale(2.0, 2.0);
1155 paint.setColor(flutter::DlColor::kYellow());
1156 builder.DrawRect(SkRect::MakeWH(300, 300), paint);
1157 paint.setStrokeWidth(1.0);
1159 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1160 builder.DrawLine(SkPoint::Make(150, 0), SkPoint::Make(150, 300), paint);
1161 builder.DrawLine(SkPoint::Make(0, 150), SkPoint::Make(300, 150), paint);
1162
1163 flutter::DlPaint save_paint;
1164 SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
1165 SkMatrix translate_matrix =
1166 SkMatrix::Translate(translation[0], translation[1]);
1167 if (enable_save_layer) {
1168 auto filter = flutter::DlMatrixImageFilter(
1170 save_paint.setImageFilter(filter.shared());
1171 builder.SaveLayer(&bounds, &save_paint);
1172 } else {
1173 builder.Save();
1174 builder.Transform(translate_matrix);
1175 }
1176
1177 SkMatrix filter_matrix = SkMatrix::I();
1178 filter_matrix.postTranslate(-150, -150);
1179 filter_matrix.postScale(0.2f, 0.2f);
1180 filter_matrix.postTranslate(150, 150);
1181 auto filter = flutter::DlMatrixImageFilter(
1183
1184 save_paint.setImageFilter(filter.shared());
1185
1186 builder.SaveLayer(&bounds, &save_paint);
1187 flutter::DlPaint paint2;
1189 builder.DrawRect(bounds, paint2);
1190 builder.Restore();
1191 builder.Restore();
1192 return builder.Build();
1193 };
1194
1195 ASSERT_TRUE(OpenPlaygroundHere(callback));
1196}
SkMatrix & postTranslate(SkScalar dx, SkScalar dy)
Definition SkMatrix.cpp:281
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition SkMatrix.cpp:360
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition SkMatrix.h:91
static const SkMatrix & I()
DlPaint & setImageFilter(const std::shared_ptr< const DlImageFilter > &filter)
Definition dl_paint.h:158

◆ TEST_P() [267/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawWithOddPathWinding   
)

Definition at line 386 of file dl_unittests.cc.

386 {
389
390 paint.setColor(flutter::DlColor::kRed());
392
393 builder.Translate(300, 300);
394 SkPath path;
395 path.setFillType(SkPathFillType::kEvenOdd);
396 path.addCircle(0, 0, 100);
397 path.addCircle(0, 0, 50);
398 builder.DrawPath(path, paint);
399
400 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
401}
@ kFill
fills interior of shapes

◆ TEST_P() [268/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawZeroLengthLine   
)

Definition at line 841 of file dl_unittests.cc.

841 {
843 std::vector<flutter::DlStrokeCap> caps = {
847 };
850 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
853 .setStrokeWidth(20);
854 SkPath path = SkPath().addPoly({{150, 50}, {150, 50}}, false);
855 for (auto cap : caps) {
856 paint.setStrokeCap(cap);
857 builder.DrawLine({50, 50}, {50, 50}, paint);
858 builder.DrawPath(path, paint);
859 builder.Translate(0, 150);
860 }
861 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
862}
DlPaint & setStrokeCap(DlStrokeCap cap)
Definition dl_paint.h:103
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:95

◆ TEST_P() [269/435]

impeller::testing::TEST_P ( DisplayListTest  ,
CanDrawZeroWidthLine   
)

Definition at line 1004 of file dl_unittests.cc.

1004 {
1006 std::vector<flutter::DlStrokeCap> caps = {
1010 };
1012 flutter::DlPaint() //
1015 .setStrokeWidth(0);
1016 flutter::DlPaint outline_paint = //
1017 flutter::DlPaint() //
1021 .setStrokeWidth(1);
1022 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1023 for (auto cap : caps) {
1024 paint.setStrokeCap(cap);
1025 builder.DrawLine({50, 50}, {60, 50}, paint);
1026 builder.DrawRect({45, 45, 65, 55}, outline_paint);
1027 builder.DrawLine({100, 50}, {100, 50}, paint);
1028 if (cap != flutter::DlStrokeCap::kButt) {
1029 builder.DrawRect({95, 45, 105, 55}, outline_paint);
1030 }
1031 builder.DrawPath(path, paint);
1032 builder.DrawRect(path.getBounds().makeOutset(5, 5), outline_paint);
1033 builder.Translate(0, 150);
1034 }
1035 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1036}

◆ TEST_P() [270/435]

impeller::testing::TEST_P ( DisplayListTest  ,
ClipDrawRRectWithNonCircularRadii   
)

Definition at line 1598 of file dl_unittests.cc.

1598 {
1600
1601 flutter::DlPaint fill_paint = //
1602 flutter::DlPaint() //
1605 .setStrokeWidth(10);
1606 flutter::DlPaint stroke_paint = //
1607 flutter::DlPaint() //
1610 .setStrokeWidth(10);
1611
1612 builder.DrawRRect(
1613 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1614 fill_paint);
1615 builder.DrawRRect(
1616 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1617 stroke_paint);
1618
1619 builder.DrawRRect(
1620 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1621 fill_paint);
1622 builder.DrawRRect(
1623 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1624 stroke_paint);
1625
1626 flutter::DlPaint reference_paint = //
1627 flutter::DlPaint() //
1630 .setStrokeWidth(10);
1631
1632 builder.DrawRRect(
1633 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1634 reference_paint);
1635 builder.DrawRRect(
1636 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1637 reference_paint);
1638
1639 flutter::DlPaint clip_fill_paint = //
1640 flutter::DlPaint() //
1643 .setStrokeWidth(10);
1644
1645 builder.Save();
1646 builder.ClipRRect(
1647 SkRRect::MakeRectXY(SkRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1648 builder.DrawPaint(clip_fill_paint);
1649 builder.Restore();
1650
1651 builder.Save();
1652 builder.ClipRRect(
1653 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1654 builder.DrawPaint(clip_fill_paint);
1655 builder.Restore();
1656
1657 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1658}
static constexpr DlColor kMidGrey()
Definition dl_color.h:31

◆ TEST_P() [271/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists   
)

Definition at line 913 of file dl_unittests.cc.

914 {
915 // Regression test for https://github.com/flutter/flutter/issues/130613
916 flutter::DisplayListBuilder sub_builder(true);
917 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
919 auto display_list = sub_builder.Build();
920
921 DlDispatcher dispatcher(Rect::MakeLTRB(0, 0, 2400, 1800));
922 dispatcher.scale(2.0, 2.0);
923 dispatcher.translate(-93.0, 0.0);
924 // clang-format off
925 dispatcher.transformFullPerspective(
926 0.8, -0.2, -0.1, -0.0,
927 0.0, 1.0, 0.0, 0.0,
928 1.4, 1.3, 1.0, 0.0,
929 63.2, 65.3, 48.6, 1.1
930 );
931 // clang-format on
932 dispatcher.translate(35.0, 75.0);
933 dispatcher.drawDisplayList(display_list, 1.0f);
934 auto picture = dispatcher.EndRecordingAsPicture();
935
936 bool found = false;
937 picture.pass->IterateAllEntities([&found](Entity& entity) {
938 if (std::static_pointer_cast<SolidColorContents>(entity.GetContents())
939 ->GetColor() == Color::Red()) {
940 found = true;
941 return false;
942 }
943
944 return true;
945 });
946 EXPECT_TRUE(found);
947}

◆ TEST_P() [272/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawMaskBlursThatMightUseSaveLayers   
)

Definition at line 1860 of file dl_unittests.cc.

1860 {
1863 Vector2 scale = GetContentScale();
1864 builder.Scale(scale.x, scale.y);
1865
1866 builder.Save();
1867 // We need a small transform op to avoid a deferred save
1868 builder.Translate(1.0f, 1.0f);
1869 auto solid_filter =
1871 flutter::DlPaint solid_alpha_paint =
1872 flutter::DlPaint() //
1873 .setMaskFilter(solid_filter) //
1875 .setAlpha(0x7f);
1876 for (int x = 1; x <= 4; x++) {
1877 for (int y = 1; y <= 4; y++) {
1878 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1879 solid_alpha_paint);
1880 }
1881 }
1882 builder.Restore();
1883
1884 builder.Save();
1885 builder.Translate(500.0f, 0.0f);
1886 auto normal_filter =
1888 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1890 flutter::DlPaint normal_if_paint =
1891 flutter::DlPaint() //
1892 .setMaskFilter(solid_filter) //
1893 .setImageFilter(rotate_if) //
1895 .setAlpha(0x7f);
1896 for (int x = 1; x <= 4; x++) {
1897 for (int y = 1; y <= 4; y++) {
1898 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1899 normal_if_paint);
1900 }
1901 }
1902 builder.Restore();
1903
1904 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1905}
static SkMatrix RotateDeg(SkScalar deg)
Definition SkMatrix.h:104
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
static std::shared_ptr< DlImageFilter > Make(const SkMatrix &matrix, DlImageSampling sampling)
DlPaint & setMaskFilter(const std::shared_ptr< DlMaskFilter > &filter)
Definition dl_paint.h:171

◆ TEST_P() [273/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawPaintIgnoresMaskFilter   
)

Definition at line 1837 of file dl_unittests.cc.

1837 {
1839 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1840
1842 builder.DrawCircle({300, 300}, 200,
1843 flutter::DlPaint().setMaskFilter(&filter));
1844
1845 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1847 const float stops[2] = {0.0, 1.0};
1849 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1851 flutter::DlPaint blend_paint =
1852 flutter::DlPaint() //
1855 builder.DrawPaint(blend_paint);
1856
1857 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1858}
DlPaint & setBlendMode(DlBlendMode mode)
Definition dl_paint.h:87
DlPaint & setColorSource(std::shared_ptr< const DlColorSource > source)
Definition dl_paint.h:132

◆ TEST_P() [274/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawShapes   
)

Definition at line 1560 of file dl_unittests.cc.

1560 {
1562 std::vector<flutter::DlStrokeJoin> joins = {
1566 };
1568 flutter::DlPaint() //
1571 .setStrokeWidth(10);
1572 flutter::DlPaint stroke_paint = //
1573 flutter::DlPaint() //
1576 .setStrokeWidth(10);
1577 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1578
1579 builder.Translate(300, 50);
1580 builder.Scale(0.8, 0.8);
1581 for (auto join : joins) {
1582 paint.setStrokeJoin(join);
1583 stroke_paint.setStrokeJoin(join);
1584 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1585 builder.DrawRect(SkRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1586 builder.DrawRRect(
1587 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 0, 100, 100), 30, 30), paint);
1588 builder.DrawRRect(
1589 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1590 stroke_paint);
1591 builder.DrawCircle({350, 50}, 50, paint);
1592 builder.DrawCircle({350, 200}, 50, stroke_paint);
1593 builder.Translate(0, 300);
1594 }
1595 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1596}
DlPaint & setStrokeJoin(DlStrokeJoin join)
Definition dl_paint.h:111

◆ TEST_P() [275/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesBlendModes   
)

Definition at line 1660 of file dl_unittests.cc.

1660 {
1661 std::vector<const char*> blend_mode_names;
1662 std::vector<flutter::DlBlendMode> blend_mode_values;
1663 {
1664 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1665 // Pipeline blends (Porter-Duff alpha compositing)
1667 {"Source", flutter::DlBlendMode::kSrc},
1668 {"Destination", flutter::DlBlendMode::kDst},
1669 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1670 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1671 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1672 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1673 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1674 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1675 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1676 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1679 {"Modulate", flutter::DlBlendMode::kModulate},
1680 // Advanced blends (color component blends)
1682 {"Overlay", flutter::DlBlendMode::kOverlay},
1684 {"Lighten", flutter::DlBlendMode::kLighten},
1685 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1686 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1687 {"HardLight", flutter::DlBlendMode::kHardLight},
1688 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1689 {"Difference", flutter::DlBlendMode::kDifference},
1690 {"Exclusion", flutter::DlBlendMode::kExclusion},
1691 {"Multiply", flutter::DlBlendMode::kMultiply},
1693 {"Saturation", flutter::DlBlendMode::kSaturation},
1695 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1696 };
1697 assert(blends.size() ==
1698 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1699 for (const auto& [name, mode] : blends) {
1700 blend_mode_names.push_back(name);
1701 blend_mode_values.push_back(mode);
1702 }
1703 }
1704
1705 auto callback = [&]() {
1706 static int current_blend_index = 3;
1707 static float dst_alpha = 1;
1708 static float src_alpha = 1;
1709 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1710 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1711 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1712 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1713
1714 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1715 {
1716 ImGui::ListBox("Blending mode", &current_blend_index,
1717 blend_mode_names.data(), blend_mode_names.size());
1718 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1719 ImGui::ColorEdit4("Color A", color0);
1720 ImGui::ColorEdit4("Color B", color1);
1721 ImGui::ColorEdit4("Color C", color2);
1722 ImGui::ColorEdit4("Source Color", src_color);
1723 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1724 }
1725 ImGui::End();
1726
1727 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1728 SkPoint::Make(200, 100),
1729 SkPoint::Make(300, 300)};
1730 std::vector<flutter::DlColor> colors = {
1731 toColor(color0).modulateOpacity(dst_alpha),
1732 toColor(color1).modulateOpacity(dst_alpha),
1733 toColor(color2).modulateOpacity(dst_alpha)};
1734
1735 auto vertices = flutter::DlVertices::Make(
1736 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1737 /*texture_coordinates=*/nullptr, colors.data());
1738
1741
1742 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1743 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1744 paint);
1745 return builder.Build();
1746 };
1747
1748 ASSERT_TRUE(OpenPlaygroundHere(callback));
1749}
@ kTriangles
The vertices are taken 3 at a time to form a triangle.
@ kSrcOut
r = s * (1-da)
@ kExclusion
rc = s + d - two(s*d), ra = kSrcOver
@ kSaturation
saturation of source with hue and luminosity of destination
@ kColorBurn
darken destination to reflect source
@ kPlus
r = min(s + d, 1)
@ kLighten
rc = s + d - min(s*da, d*sa), ra = kSrcOver
@ kHue
hue of source with saturation and luminosity of destination
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kColorDodge
brighten destination to reflect source
@ kXor
r = s*(1-da) + d*(1-sa)
@ kLuminosity
luminosity of source with hue and saturation of destination
@ kSoftLight
lighten or darken, depending on source
@ kDifference
rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
@ kOverlay
multiply or screen, depending on destination
@ kSrcATop
r = s*da + d*(1-sa)
@ kDstATop
r = d*sa + s*(1-da)
@ kLastMode
last valid value
@ kColor
hue and saturation of source with luminosity of destination
@ kHardLight
multiply or screen, depending on source
@ kDstOut
r = d * (1-sa)
@ kDarken
rc = s + d - max(s*da, d*sa), ra = kSrcOver
flutter::DlColor toColor(const float *components)
constexpr DlColor modulateOpacity(float opacity) const
Definition dl_color.h:72

◆ TEST_P() [276/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesImageSourceWithTextureCoordinates   
)

Definition at line 1462 of file dl_unittests.cc.

1462 {
1463 auto texture = CreateTextureForFixture("embarcadero.jpg");
1464 auto dl_image = DlImageImpeller::Make(texture);
1465 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1466 SkPoint::Make(200, 100),
1467 SkPoint::Make(300, 300)};
1468 std::vector<SkPoint> texture_coordinates = {
1469 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1470
1471 auto vertices = flutter::DlVertices::Make(
1472 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1473 texture_coordinates.data(), /*colors=*/nullptr);
1474
1477
1478 auto image_source = flutter::DlImageColorSource(
1480
1481 paint.setColorSource(&image_source);
1482 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1483
1484 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1485}

◆ TEST_P() [277/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending   
)

Definition at line 1487 of file dl_unittests.cc.

1488 {
1489 auto texture = CreateTextureForFixture("embarcadero.jpg");
1490 auto dl_image = DlImageImpeller::Make(texture);
1491 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1492 SkPoint::Make(200, 100),
1493 SkPoint::Make(300, 300)};
1494 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1497 std::vector<SkPoint> texture_coordinates = {
1498 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1499
1500 auto vertices = flutter::DlVertices::Make(
1501 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1502 texture_coordinates.data(), colors.data());
1503
1506
1507 auto image_source = flutter::DlImageColorSource(
1509
1510 paint.setColorSource(&image_source);
1511 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
1512
1513 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1514}

◆ TEST_P() [278/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesLinearGradientWithoutIndices   
)

Definition at line 1407 of file dl_unittests.cc.

1407 {
1408 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1409 SkPoint::Make(200, 100),
1410 SkPoint::Make(300, 300)};
1411
1412 auto vertices = flutter::DlVertices::Make(
1413 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1414 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
1415
1416 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1418 const float stops[2] = {0.0, 1.0};
1419
1421 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1423
1426
1427 paint.setColorSource(linear);
1428 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1429
1430 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1431}

◆ TEST_P() [279/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesLinearGradientWithTextureCoordinates   
)

Definition at line 1433 of file dl_unittests.cc.

1433 {
1434 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1435 SkPoint::Make(200, 100),
1436 SkPoint::Make(300, 300)};
1437 std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
1438 SkPoint::Make(100, 200),
1439 SkPoint::Make(300, 300)};
1440
1441 auto vertices = flutter::DlVertices::Make(
1442 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1443 texture_coordinates.data(), /*colors=*/nullptr);
1444
1445 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1447 const float stops[2] = {0.0, 1.0};
1448
1450 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1452
1455
1456 paint.setColorSource(linear);
1457 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1458
1459 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1460}

◆ TEST_P() [280/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesPremultipliesColors   
)

Definition at line 1536 of file dl_unittests.cc.

1536 {
1537 std::vector<SkPoint> positions = {
1538 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1539 SkPoint::Make(200, 500)};
1541 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1542 std::vector<flutter::DlColor> colors = {color, color, color, color};
1543
1544 auto vertices = flutter::DlVertices::Make(
1545 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
1546 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
1547 indices.data());
1548
1552 paint.setColor(flutter::DlColor::kRed());
1553
1554 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
1555 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
1556
1557 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1558}
constexpr DlColor withAlpha(uint8_t alpha) const
Definition dl_color.h:59

◆ TEST_P() [281/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesSolidColorTrianglesWithIndices   
)

Definition at line 1516 of file dl_unittests.cc.

1516 {
1517 std::vector<SkPoint> positions = {
1518 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1519 SkPoint::Make(200, 500)};
1520 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1521
1522 auto vertices = flutter::DlVertices::Make(
1523 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
1524 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
1525 indices.data());
1526
1529
1530 paint.setColor(flutter::DlColor::kWhite());
1531 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1532
1533 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1534}

◆ TEST_P() [282/435]

impeller::testing::TEST_P ( DisplayListTest  ,
DrawVerticesSolidColorTrianglesWithoutIndices   
)

Definition at line 1383 of file dl_unittests.cc.

1383 {
1384 // Use negative coordinates and then scale the transform by -1, -1 to make
1385 // sure coverage is taking the transform into account.
1386 std::vector<SkPoint> positions = {SkPoint::Make(-100, -300),
1387 SkPoint::Make(-200, -100),
1388 SkPoint::Make(-300, -300)};
1389 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1392
1393 auto vertices = flutter::DlVertices::Make(
1394 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1395 /*texture_coordinates=*/nullptr, colors.data());
1396
1399
1400 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
1401 builder.Scale(-1, -1);
1402 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1403
1404 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1405}

◆ TEST_P() [283/435]

impeller::testing::TEST_P ( DisplayListTest  ,
IgnoreMaskFilterWhenSavingLayer   
)

Definition at line 505 of file dl_unittests.cc.

505 {
506 auto texture = CreateTextureForFixture("embarcadero.jpg");
510 paint.setMaskFilter(&filter);
511 builder.SaveLayer(nullptr, &paint);
512 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
514 builder.Restore();
515 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
516}

◆ TEST_P() [284/435]

impeller::testing::TEST_P ( DisplayListTest  ,
MaskBlursApplyCorrectlyToColorSources   
)

Definition at line 1346 of file dl_unittests.cc.

1346 {
1347 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1349
1351
1352 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1354 std::array<float, 2> stops = {0, 1};
1355 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1356 std::make_shared<flutter::DlColorColorSource>(flutter::DlColor::kWhite()),
1358 SkPoint::Make(0, 0), SkPoint::Make(100, 50), 2, colors.data(),
1359 stops.data(), flutter::DlTileMode::kClamp)};
1360
1361 int offset = 100;
1362 for (const auto& color_source : color_sources) {
1364 paint.setColorSource(color_source);
1365 paint.setMaskFilter(blur_filter);
1366
1367 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1368 builder.DrawRRect(
1369 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, offset, 100, 50), 30, 30),
1370 paint);
1372 paint.setStrokeWidth(10);
1373 builder.DrawRRect(
1374 SkRRect::MakeRectXY(SkRect::MakeXYWH(300, offset, 100, 50), 30, 30),
1375 paint);
1376
1377 offset += 100;
1378 }
1379
1380 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1381}

◆ TEST_P() [285/435]

impeller::testing::TEST_P ( DisplayListTest  ,
NinePatchImagePrecision   
)

Definition at line 793 of file dl_unittests.cc.

793 {
794 // Draw a nine patch image with colored corners and verify that the corner
795 // color does not leak outside the intended region.
796 auto texture = CreateTextureForFixture("nine_patch_corners.png");
798 builder.DrawImageNine(DlImageImpeller::Make(texture),
799 SkIRect::MakeXYWH(10, 10, 1, 1),
800 SkRect::MakeXYWH(0, 0, 200, 100),
802 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
803}
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition SkRect.h:104

◆ TEST_P() [286/435]

impeller::testing::TEST_P ( DisplayListTest  ,
StrokedPathsDrawCorrectly   
)

Definition at line 213 of file dl_unittests.cc.

213 {
214 auto callback = [&]() {
217
218 paint.setColor(flutter::DlColor::kRed());
220
221 static float stroke_width = 10.0f;
222 static int selected_stroke_type = 0;
223 static int selected_join_type = 0;
224 const char* stroke_types[] = {"Butte", "Round", "Square"};
225 const char* join_type[] = {"kMiter", "Round", "kBevel"};
226
227 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
228 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
229 sizeof(stroke_types) / sizeof(char*));
230 ImGui::Combo("Join", &selected_join_type, join_type,
231 sizeof(join_type) / sizeof(char*));
232 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
233 ImGui::End();
234
237 switch (selected_stroke_type) {
238 case 0:
240 break;
241 case 1:
243 break;
244 case 2:
246 break;
247 default:
249 break;
250 }
251 switch (selected_join_type) {
252 case 0:
254 break;
255 case 1:
257 break;
258 case 2:
260 break;
261 default:
263 break;
264 }
265 paint.setStrokeCap(cap);
266 paint.setStrokeJoin(join);
267 paint.setStrokeWidth(stroke_width);
268
269 // Make rendering better to watch.
270 builder.Scale(1.5f, 1.5f);
271
272 // Rectangle
273 builder.Translate(100, 100);
274 builder.DrawRect(SkRect::MakeSize({100, 100}), paint);
275
276 // Rounded rectangle
277 builder.Translate(150, 0);
278 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
279 paint);
280
281 // Double rounded rectangle
282 builder.Translate(150, 0);
283 builder.DrawDRRect(
284 SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
285 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint);
286
287 // Contour with duplicate join points
288 {
289 builder.Translate(150, 0);
290 SkPath path;
291 path.moveTo(0, 0);
292 path.lineTo(0, 0);
293 path.lineTo({100, 0});
294 path.lineTo({100, 0});
295 path.lineTo({100, 100});
296 builder.DrawPath(path, paint);
297 }
298
299 // Contour with duplicate start and end points
300
301 // Line.
302 builder.Translate(200, 0);
303 {
304 builder.Save();
305
306 SkPath line_path;
307 line_path.moveTo(0, 0);
308 line_path.moveTo(0, 0);
309 line_path.lineTo({0, 0});
310 line_path.lineTo({0, 0});
311 line_path.lineTo({50, 50});
312 line_path.lineTo({50, 50});
313 line_path.lineTo({100, 0});
314 line_path.lineTo({100, 0});
315 builder.DrawPath(line_path, paint);
316
317 builder.Translate(0, 100);
318 builder.DrawPath(line_path, paint);
319
320 builder.Translate(0, 100);
321 SkPath line_path2;
322 line_path2.moveTo(0, 0);
323 line_path2.lineTo(0, 0);
324 line_path2.lineTo(0, 0);
325 builder.DrawPath(line_path2, paint);
326
327 builder.Restore();
328 }
329
330 // Cubic.
331 builder.Translate(150, 0);
332 {
333 builder.Save();
334
336 cubic_path.moveTo({0, 0});
337 cubic_path.cubicTo(0, 0, 140.0, 100.0, 140, 20);
338 builder.DrawPath(cubic_path, paint);
339
340 builder.Translate(0, 100);
341 SkPath cubic_path2;
342 cubic_path2.moveTo({0, 0});
343 cubic_path2.cubicTo(0, 0, 0, 0, 150, 150);
344 builder.DrawPath(cubic_path2, paint);
345
346 builder.Translate(0, 100);
347 SkPath cubic_path3;
348 cubic_path3.moveTo({0, 0});
349 cubic_path3.cubicTo(0, 0, 0, 0, 0, 0);
350 builder.DrawPath(cubic_path3, paint);
351
352 builder.Restore();
353 }
354
355 // Quad.
356 builder.Translate(200, 0);
357 {
358 builder.Save();
359
361 quad_path.moveTo(0, 0);
362 quad_path.moveTo(0, 0);
363 quad_path.quadTo({100, 40}, {50, 80});
364 builder.DrawPath(quad_path, paint);
365
366 builder.Translate(0, 150);
367 SkPath quad_path2;
368 quad_path2.moveTo(0, 0);
369 quad_path2.moveTo(0, 0);
370 quad_path2.quadTo({0, 0}, {100, 100});
371 builder.DrawPath(quad_path2, paint);
372
373 builder.Translate(0, 100);
374 SkPath quad_path3;
375 quad_path3.moveTo(0, 0);
376 quad_path3.quadTo({0, 0}, {0, 0});
377 builder.DrawPath(quad_path3, paint);
378
379 builder.Restore();
380 }
381 return builder.Build();
382 };
383 ASSERT_TRUE(OpenPlaygroundHere(callback));
384}
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
SkPath & lineTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:718
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition SkPath.cpp:736
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition SkPath.cpp:789
DlStrokeJoin
Definition dl_paint.h:38
SkPath quad_path()
SkPath cubic_path()

◆ TEST_P() [287/435]

impeller::testing::TEST_P ( DisplayListTest  ,
StrokedTextNotOffsetFromNormalText   
)

Definition at line 480 of file dl_unittests.cc.

480 {
483 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
484
485 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
486 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
487
488 // Draw a blue filled rectangle so the text is easier to see.
490 paint.setColor(mat_blue);
491 builder.DrawRect(SkRect::MakeXYWH(0, 0, 500, 500), paint);
492
493 // Draw stacked text, with stroked text on top.
496 builder.DrawTextBlob(text_blob, 250, 250, paint);
497
500 builder.DrawTextBlob(text_blob, 250, 250, paint);
501
502 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
503}

◆ TEST_P() [288/435]

impeller::testing::TEST_P ( DisplayListTest  ,
TransparentShadowProducesCorrectColor   
)

Definition at line 949 of file dl_unittests.cc.

949 {
950 DlDispatcher dispatcher;
951 dispatcher.save();
952 dispatcher.scale(1.618, 1.618);
953 SkPath path = SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100));
955 dispatcher.drawShadow(cache, flutter::DlColor::kTransparent(), 15, false, 1);
956 dispatcher.restore();
957 auto picture = dispatcher.EndRecordingAsPicture();
958
959 std::shared_ptr<SolidRRectBlurContents> rrect_blur;
960 picture.pass->IterateAllEntities([&rrect_blur](Entity& entity) {
961 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
962 rrect_blur = std::static_pointer_cast<SolidRRectBlurContents>(
963 entity.GetContents());
964 return false;
965 }
966 return true;
967 });
968
969 ASSERT_NE(rrect_blur, nullptr);
970 ASSERT_EQ(rrect_blur->GetColor().red, 0);
971 ASSERT_EQ(rrect_blur->GetColor().green, 0);
972 ASSERT_EQ(rrect_blur->GetColor().blue, 0);
973 ASSERT_EQ(rrect_blur->GetColor().alpha, 0);
974}
void drawShadow(const SkPath &path, const flutter::DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) override
void scale(SkScalar sx, SkScalar sy) override
static constexpr DlColor kTransparent()
Definition dl_color.h:21

◆ TEST_P() [289/435]

impeller::testing::TEST_P ( DriverInfoVKTest  ,
CanDumpToLog   
)

Definition at line 26 of file driver_info_vk_unittests.cc.

26 {
27 ASSERT_TRUE(GetContext());
28 const auto& driver_info =
29 SurfaceContextVK::Cast(*GetContext()).GetParent().GetDriverInfo();
30 ASSERT_NE(driver_info, nullptr);
32 driver_info->DumpToLog();
33 ASSERT_TRUE(log.str().find("Driver Information") != std::string::npos);
34}

◆ TEST_P() [290/435]

impeller::testing::TEST_P ( DriverInfoVKTest  ,
CanQueryDriverInfo   
)

Definition at line 14 of file driver_info_vk_unittests.cc.

14 {
15 ASSERT_TRUE(GetContext());
16 const auto& driver_info =
17 SurfaceContextVK::Cast(*GetContext()).GetParent().GetDriverInfo();
18 ASSERT_NE(driver_info, nullptr);
19 // 1.1 is the base Impeller version. The driver can't be lower than that.
20 ASSERT_TRUE(driver_info->GetAPIVersion().IsAtLeast(Version{1, 1, 0}));
21 ASSERT_NE(driver_info->GetVendor(), VendorVK::kUnknown);
22 ASSERT_NE(driver_info->GetDeviceType(), DeviceTypeVK::kUnknown);
23 ASSERT_NE(driver_info->GetDriverName(), "");
24}

◆ TEST_P() [291/435]

impeller::testing::TEST_P ( EntityPassTargetTest  ,
SwapWithMSAAImplicitResolve   
)

Definition at line 53 of file entity_pass_target_unittests.cc.

53 {
54 auto content_context = GetContentContext();
55 auto buffer = content_context->GetContext()->CreateCommandBuffer();
56 auto context = content_context->GetContext();
57 auto& allocator = *context->GetResourceAllocator();
58
59 // Emulate implicit MSAA resolve by making color resolve and msaa texture the
60 // same.
61 RenderTarget render_target;
62 {
63 PixelFormat pixel_format =
64 context->GetCapabilities()->GetDefaultColorFormat();
65
66 // Create MSAA color texture.
67
68 TextureDescriptor color0_tex_desc;
69 color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
70 color0_tex_desc.type = TextureType::kTexture2DMultisample;
71 color0_tex_desc.sample_count = SampleCount::kCount4;
72 color0_tex_desc.format = pixel_format;
73 color0_tex_desc.size = ISize{100, 100};
74 color0_tex_desc.usage = TextureUsage::kRenderTarget;
75
76 auto color0_msaa_tex = allocator.CreateTexture(color0_tex_desc);
77
78 // Color attachment.
79
80 ColorAttachment color0;
81 color0.load_action = LoadAction::kDontCare;
82 color0.store_action = StoreAction::kStoreAndMultisampleResolve;
83 color0.texture = color0_msaa_tex;
84 color0.resolve_texture = color0_msaa_tex;
85
86 render_target.SetColorAttachment(color0, 0u);
87 render_target.SetStencilAttachment(std::nullopt);
88 }
89
90 auto entity_pass_target = EntityPassTarget(render_target, false, true);
91
92 auto color0 = entity_pass_target.GetRenderTarget()
93 .GetColorAttachments()
94 .find(0u)
95 ->second;
96 auto msaa_tex = color0.texture;
97 auto resolve_tex = color0.resolve_texture;
98
99 ASSERT_EQ(msaa_tex, resolve_tex);
100
101 entity_pass_target.Flip(
102 *content_context->GetContext()->GetResourceAllocator());
103
104 color0 = entity_pass_target.GetRenderTarget()
105 .GetColorAttachments()
106 .find(0u)
107 ->second;
108
109 ASSERT_NE(msaa_tex, color0.texture);
110 ASSERT_NE(resolve_tex, color0.resolve_texture);
111 ASSERT_EQ(color0.texture, color0.resolve_texture);
112}
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
std::shared_ptr< Texture > resolve_texture
Definition formats.h:640
LoadAction load_action
Definition formats.h:641
std::shared_ptr< Texture > texture
Definition formats.h:639
StoreAction store_action
Definition formats.h:642

◆ TEST_P() [292/435]

impeller::testing::TEST_P ( EntityPassTargetTest  ,
SwapWithMSAATexture   
)

Definition at line 19 of file entity_pass_target_unittests.cc.

19 {
20 if (GetContentContext()
21 ->GetDeviceCapabilities()
22 .SupportsImplicitResolvingMSAA()) {
23 GTEST_SKIP() << "Implicit MSAA is used on this device.";
24 }
25 auto content_context = GetContentContext();
26 auto buffer = content_context->GetContext()->CreateCommandBuffer();
27 auto render_target =
28 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
29 *content_context->GetContext(), {100, 100},
30 /*mip_count=*/1);
31
32 auto entity_pass_target = EntityPassTarget(render_target, false, false);
33
34 auto color0 = entity_pass_target.GetRenderTarget()
35 .GetColorAttachments()
36 .find(0u)
37 ->second;
38 auto msaa_tex = color0.texture;
39 auto resolve_tex = color0.resolve_texture;
40
41 entity_pass_target.Flip(
42 *content_context->GetContext()->GetResourceAllocator());
43
44 color0 = entity_pass_target.GetRenderTarget()
45 .GetColorAttachments()
46 .find(0u)
47 ->second;
48
49 ASSERT_EQ(msaa_tex, color0.texture);
50 ASSERT_NE(resolve_tex, color0.resolve_texture);
51}

◆ TEST_P() [293/435]

impeller::testing::TEST_P ( EntityTest  ,
AdvancedBlendCoverageHintIsNotResetByEntityPass   
)

Definition at line 2571 of file entity_unittests.cc.

2571 {
2572 if (GetContext()->GetCapabilities()->SupportsFramebufferFetch()) {
2573 GTEST_SKIP() << "Backends that support framebuffer fetch dont use coverage "
2574 "for advanced blends.";
2575 }
2576
2577 auto contents = std::make_shared<SolidColorContents>();
2578 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
2579 contents->SetColor(Color::Red());
2580
2581 Entity entity;
2582 entity.SetTransform(Matrix::MakeScale(Vector3(2, 2, 1)));
2583 entity.SetBlendMode(BlendMode::kColorBurn);
2584 entity.SetContents(contents);
2585
2586 auto coverage = entity.GetCoverage();
2587 EXPECT_TRUE(coverage.has_value());
2588
2589 auto pass = std::make_unique<EntityPass>();
2590 std::shared_ptr<RenderTargetCache> render_target_allocator =
2591 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
2592 auto stencil_config = RenderTarget::AttachmentConfig{
2593 .storage_mode = StorageMode::kDevicePrivate,
2594 .load_action = LoadAction::kClear,
2595 .store_action = StoreAction::kDontCare,
2596 .clear_color = Color::BlackTransparent()};
2597 auto rt = render_target_allocator->CreateOffscreen(
2598 *GetContext(), ISize::MakeWH(1000, 1000),
2599 /*mip_count=*/1, "Offscreen", RenderTarget::kDefaultColorAttachmentConfig,
2600 stencil_config);
2601 auto content_context = ContentContext(
2602 GetContext(), TypographerContextSkia::Make(), render_target_allocator);
2603 pass->AddEntity(std::move(entity));
2604
2605 EXPECT_TRUE(pass->Render(content_context, rt));
2606
2607 auto contains_size = [&render_target_allocator](ISize size) -> bool {
2608 return std::find_if(render_target_allocator->GetRenderTargetDataBegin(),
2609 render_target_allocator->GetRenderTargetDataEnd(),
2610 [&size](const auto& data) {
2611 return data.config.size == size;
2612 }) != render_target_allocator->GetRenderTargetDataEnd();
2613 };
2614
2615 EXPECT_TRUE(contains_size(ISize(1000, 1000)))
2616 << "The root texture wasn't allocated";
2617 EXPECT_TRUE(contains_size(ISize(200, 200)))
2618 << "The ColorBurned texture wasn't allocated (100x100 scales up 2x)";
2619}
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Definition entity.cc:62
std::optional< Rect > GetCoverage() const
Definition entity.cc:66
void SetBlendMode(BlendMode blend_mode)
Definition entity.cc:115

◆ TEST_P() [294/435]

impeller::testing::TEST_P ( EntityTest  ,
BezierCircleScaled   
)

Definition at line 989 of file entity_unittests.cc.

989 {
990 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
991 static float scale = 20;
992
993 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
994 ImGui::SliderFloat("Scale", &scale, 1, 100);
995 ImGui::End();
996
997 Entity entity;
998 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
999 auto path = PathBuilder{}
1000 .MoveTo({97.325, 34.818})
1001 .CubicCurveTo({98.50862885295136, 34.81812293973836},
1002 {99.46822048142015, 33.85863261475589},
1003 {99.46822048142015, 32.67499810206613})
1004 .CubicCurveTo({99.46822048142015, 31.491363589376355},
1005 {98.50862885295136, 30.53187326439389},
1006 {97.32499434685802, 30.531998226542708})
1007 .CubicCurveTo({96.14153655073771, 30.532123170035373},
1008 {95.18222070648729, 31.491540299350355},
1009 {95.18222070648729, 32.67499810206613})
1010 .CubicCurveTo({95.18222070648729, 33.85845590478189},
1011 {96.14153655073771, 34.81787303409686},
1012 {97.32499434685802, 34.81799797758954})
1013 .Close()
1014 .TakePath();
1015 entity.SetTransform(
1016 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
1017 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
1018 return entity.Render(context, pass);
1019 };
1020 ASSERT_TRUE(OpenPlaygroundHere(callback));
1021}
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
Definition entity.cc:173

◆ TEST_P() [295/435]

impeller::testing::TEST_P ( EntityTest  ,
BlendingModeOptions   
)

Definition at line 861 of file entity_unittests.cc.

861 {
862 std::vector<const char*> blend_mode_names;
863 std::vector<BlendMode> blend_mode_values;
864 {
865 // Force an exhausiveness check with a switch. When adding blend modes,
866 // update this switch with a new name/value to make it selectable in the
867 // test GUI.
868
869 const BlendMode b{};
870 static_assert(b == BlendMode::kClear); // Ensure the first item in
871 // the switch is the first
872 // item in the enum.
873 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
874 switch (b) {
875 case BlendMode::kClear:
876 blend_mode_names.push_back("Clear");
877 blend_mode_values.push_back(BlendMode::kClear);
878 case BlendMode::kSource:
879 blend_mode_names.push_back("Source");
880 blend_mode_values.push_back(BlendMode::kSource);
881 case BlendMode::kDestination:
882 blend_mode_names.push_back("Destination");
883 blend_mode_values.push_back(BlendMode::kDestination);
884 case BlendMode::kSourceOver:
885 blend_mode_names.push_back("SourceOver");
886 blend_mode_values.push_back(BlendMode::kSourceOver);
887 case BlendMode::kDestinationOver:
888 blend_mode_names.push_back("DestinationOver");
889 blend_mode_values.push_back(BlendMode::kDestinationOver);
890 case BlendMode::kSourceIn:
891 blend_mode_names.push_back("SourceIn");
892 blend_mode_values.push_back(BlendMode::kSourceIn);
893 case BlendMode::kDestinationIn:
894 blend_mode_names.push_back("DestinationIn");
895 blend_mode_values.push_back(BlendMode::kDestinationIn);
896 case BlendMode::kSourceOut:
897 blend_mode_names.push_back("SourceOut");
898 blend_mode_values.push_back(BlendMode::kSourceOut);
899 case BlendMode::kDestinationOut:
900 blend_mode_names.push_back("DestinationOut");
901 blend_mode_values.push_back(BlendMode::kDestinationOut);
902 case BlendMode::kSourceATop:
903 blend_mode_names.push_back("SourceATop");
904 blend_mode_values.push_back(BlendMode::kSourceATop);
905 case BlendMode::kDestinationATop:
906 blend_mode_names.push_back("DestinationATop");
907 blend_mode_values.push_back(BlendMode::kDestinationATop);
908 case BlendMode::kXor:
909 blend_mode_names.push_back("Xor");
910 blend_mode_values.push_back(BlendMode::kXor);
911 case BlendMode::kPlus:
912 blend_mode_names.push_back("Plus");
913 blend_mode_values.push_back(BlendMode::kPlus);
914 case BlendMode::kModulate:
915 blend_mode_names.push_back("Modulate");
916 blend_mode_values.push_back(BlendMode::kModulate);
917 };
918 }
919
920 auto callback = [&](ContentContext& context, RenderPass& pass) {
921 auto world_matrix = Matrix::MakeScale(GetContentScale());
922 auto draw_rect = [&context, &pass, &world_matrix](
923 Rect rect, Color color, BlendMode blend_mode) -> bool {
924 using VS = SolidFillPipeline::VertexShader;
925
926 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
927 {
928 auto r = rect.GetLTRB();
929 vtx_builder.AddVertices({
930 {Point(r[0], r[1])},
931 {Point(r[2], r[1])},
932 {Point(r[2], r[3])},
933 {Point(r[0], r[1])},
934 {Point(r[2], r[3])},
935 {Point(r[0], r[3])},
936 });
937 }
938
939 pass.SetCommandLabel("Blended Rectangle");
940 auto options = OptionsFromPass(pass);
941 options.blend_mode = blend_mode;
942 options.primitive_type = PrimitiveType::kTriangle;
943 pass.SetPipeline(context.GetSolidFillPipeline(options));
944 pass.SetVertexBuffer(
945 vtx_builder.CreateVertexBuffer(context.GetTransientsBuffer()));
946
947 VS::FrameInfo frame_info;
948 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
949 frame_info.color = color.Premultiply();
950 VS::BindFrameInfo(
951 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
952
953 return pass.Draw().ok();
954 };
955
956 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
957 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
958 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
959 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
960 static int current_blend_index = 3;
961 ImGui::ListBox("Blending mode", &current_blend_index,
962 blend_mode_names.data(), blend_mode_names.size());
963 ImGui::End();
964
965 BlendMode selected_mode = blend_mode_values[current_blend_index];
966
967 Point a, b, c, d;
968 static PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
969 static PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
970 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
971 static PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
972 static PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
973 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
974
975 bool result = true;
976 result = result &&
977 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
978 pass.GetRenderTargetSize().height),
979 Color(), BlendMode::kClear);
980 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
981 BlendMode::kSourceOver);
982 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
983 selected_mode);
984 return result;
985 };
986 ASSERT_TRUE(OpenPlaygroundHere(callback));
987}
static void draw_rect(SkCanvas *canvas, SkImage *, const SkRect &r, sk_sp< SkImageFilter > imf)
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition contents.cc:20

◆ TEST_P() [296/435]

impeller::testing::TEST_P ( EntityTest  ,
BorderMaskBlurCoverageIsCorrect   
)

Definition at line 1390 of file entity_unittests.cc.

1390 {
1391 auto fill = std::make_shared<SolidColorContents>();
1392 fill->SetGeometry(Geometry::MakeFillPath(
1393 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1394 fill->SetColor(Color::CornflowerBlue());
1395 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1396 FilterInput::Make(fill), Radius{3}, Radius{4});
1397
1398 {
1399 Entity e;
1400 e.SetTransform(Matrix());
1401 auto actual = border_mask_blur->GetCoverage(e);
1402 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1403 ASSERT_TRUE(actual.has_value());
1404 ASSERT_RECT_NEAR(actual.value(), expected);
1405 }
1406
1407 {
1408 Entity e;
1409 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1410 auto actual = border_mask_blur->GetCoverage(e);
1411 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1412 ASSERT_TRUE(actual.has_value());
1413 ASSERT_RECT_NEAR(actual.value(), expected);
1414 }
1415}

◆ TEST_P() [297/435]

impeller::testing::TEST_P ( EntityTest  ,
CanComputeGeometryForEmptyPathsWithoutCrashing   
)

Definition at line 2750 of file entity_unittests.cc.

2750 {
2751 PathBuilder builder = {};
2752 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2753 Path path = builder.TakePath();
2754
2755 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2756
2757 auto geom = Geometry::MakeFillPath(path);
2758
2759 Entity entity;
2761 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2762 *GetContext(), {1, 1}, 1u);
2763 testing::MockRenderPass render_pass(GetContext(), target);
2764 auto position_result =
2765 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2766
2767 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2768
2769 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2770}
uint32_t * target

◆ TEST_P() [298/435]

impeller::testing::TEST_P ( EntityTest  ,
CanCreateEntity   
)

Definition at line 70 of file entity_unittests.cc.

70 {
71 Entity entity;
72 ASSERT_TRUE(entity.GetTransform().IsIdentity());
73}
constexpr bool IsIdentity() const
Definition matrix.h:377

◆ TEST_P() [299/435]

impeller::testing::TEST_P ( EntityTest  ,
CanDrawCorrectlyWithRotatedTransform   
)

Definition at line 545 of file entity_unittests.cc.

545 {
546 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
547 const char* input_axis[] = {"X", "Y", "Z"};
548 static int rotation_axis_index = 0;
549 static float rotation = 0;
550 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
551 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
552 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
553 sizeof(input_axis) / sizeof(char*));
554 Matrix rotation_matrix;
555 switch (rotation_axis_index) {
556 case 0:
557 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
558 break;
559 case 1:
560 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
561 break;
562 case 2:
563 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
564 break;
565 default:
566 rotation_matrix = Matrix{};
567 break;
568 }
569
570 if (ImGui::Button("Reset")) {
571 rotation = 0;
572 }
573 ImGui::End();
574 Matrix current_transform =
575 Matrix::MakeScale(GetContentScale())
576 .MakeTranslation(
577 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
578 pass.GetRenderTargetSize().height / 2.0)));
579 Matrix result_transform = current_transform * rotation_matrix;
580 Path path =
581 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
582
583 Entity entity;
584 entity.SetTransform(result_transform);
585 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
586 return entity.Render(context, pass);
587 };
588 ASSERT_TRUE(OpenPlaygroundHere(callback));
589}

◆ TEST_P() [300/435]

impeller::testing::TEST_P ( EntityTest  ,
CanDrawRect   
)

Definition at line 264 of file entity_unittests.cc.

264 {
265 auto contents = std::make_shared<SolidColorContents>();
266 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
267 contents->SetColor(Color::Red());
268
269 Entity entity;
270 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
271 entity.SetContents(contents);
272
273 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
274}

◆ TEST_P() [301/435]

impeller::testing::TEST_P ( EntityTest  ,
CanDrawRRect   
)

Definition at line 276 of file entity_unittests.cc.

276 {
277 auto contents = std::make_shared<SolidColorContents>();
278 auto path = PathBuilder{}
279 .SetConvexity(Convexity::kConvex)
280 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10.0)
281 .TakePath();
282 contents->SetGeometry(Geometry::MakeFillPath(path));
283 contents->SetColor(Color::Red());
284
285 Entity entity;
286 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
287 entity.SetContents(contents);
288
289 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
290}
PathBuilder & AddRoundedRect(Rect rect, RoundingRadii radii)

◆ TEST_P() [302/435]

impeller::testing::TEST_P ( EntityTest  ,
CanRenderEmptyPathsWithoutCrashing   
)

Definition at line 2772 of file entity_unittests.cc.

2772 {
2773 PathBuilder builder = {};
2774 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2775 Path path = builder.TakePath();
2776
2777 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2778
2779 auto contents = std::make_shared<SolidColorContents>();
2780 contents->SetGeometry(Geometry::MakeFillPath(path));
2781 contents->SetColor(Color::Red());
2782
2783 Entity entity;
2784 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2785 entity.SetContents(contents);
2786
2787 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2788}

◆ TEST_P() [303/435]

impeller::testing::TEST_P ( EntityTest  ,
ClipContentsGetClipCoverageIsCorrect   
)

Definition at line 1726 of file entity_unittests.cc.

1726 {
1727 // Intersection: No stencil coverage, no geometry.
1728 {
1729 auto clip = std::make_shared<ClipContents>();
1730 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1731 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1732
1733 ASSERT_FALSE(result.coverage.has_value());
1734 }
1735
1736 // Intersection: No stencil coverage, with geometry.
1737 {
1738 auto clip = std::make_shared<ClipContents>();
1739 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1740 clip->SetGeometry(Geometry::MakeFillPath(
1741 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1742 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1743
1744 ASSERT_FALSE(result.coverage.has_value());
1745 }
1746
1747 // Intersection: With stencil coverage, no geometry.
1748 {
1749 auto clip = std::make_shared<ClipContents>();
1750 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1751 auto result =
1752 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1753
1754 ASSERT_FALSE(result.coverage.has_value());
1755 }
1756
1757 // Intersection: With stencil coverage, with geometry.
1758 {
1759 auto clip = std::make_shared<ClipContents>();
1760 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1761 clip->SetGeometry(Geometry::MakeFillPath(
1762 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1763 auto result =
1764 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1765
1766 ASSERT_TRUE(result.coverage.has_value());
1767 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
1768 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1769 }
1770
1771 // Difference: With stencil coverage, with geometry.
1772 {
1773 auto clip = std::make_shared<ClipContents>();
1774 clip->SetClipOperation(Entity::ClipOperation::kDifference);
1775 clip->SetGeometry(Geometry::MakeFillPath(
1776 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1777 auto result =
1778 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1779
1780 ASSERT_TRUE(result.coverage.has_value());
1781 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
1782 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1783 }
1784}
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824

◆ TEST_P() [304/435]

impeller::testing::TEST_P ( EntityTest  ,
ClipContentsOptimizesFullScreenIntersectClips   
)

Definition at line 24 of file clip_contents_unittests.cc.

24 {
25 // Set up mock environment.
26
27 auto content_context = GetContentContext();
28 auto buffer = content_context->GetContext()->CreateCommandBuffer();
29 auto render_target =
30 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
31 *content_context->GetContext(), {100, 100},
32 /*mip_count=*/1);
33 auto render_pass = buffer->CreateRenderPass(render_target);
34 auto recording_pass = std::make_shared<RecordingRenderPass>(
35 render_pass, GetContext(), render_target);
36
37 // Set up clip contents.
38
39 auto contents = std::make_shared<ClipContents>();
40 contents->SetClipOperation(Entity::ClipOperation::kIntersect);
41 contents->SetGeometry(Geometry::MakeCover());
42
43 Entity entity;
44 entity.SetContents(std::move(contents));
45
46 // Render the clip contents.
47
48 ASSERT_TRUE(recording_pass->GetCommands().empty());
49 ASSERT_TRUE(entity.Render(*content_context, *recording_pass));
50 ASSERT_FALSE(recording_pass->GetCommands().empty());
51}

◆ TEST_P() [305/435]

impeller::testing::TEST_P ( EntityTest  ,
ClipContentsShouldRenderIsCorrect   
)

Definition at line 1702 of file entity_unittests.cc.

1702 {
1703 // For clip ops, `ShouldRender` should always return true.
1704
1705 // Clip.
1706 {
1707 auto clip = std::make_shared<ClipContents>();
1708 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1709 clip->SetGeometry(Geometry::MakeFillPath(
1710 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1711 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1712 ASSERT_TRUE(
1713 clip->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1714 }
1715
1716 // Clip restore.
1717 {
1718 auto restore = std::make_shared<ClipRestoreContents>();
1719 ASSERT_TRUE(
1720 restore->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1721 ASSERT_TRUE(
1722 restore->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1723 }
1724}

◆ TEST_P() [306/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorFilterContentsWithLargeGeometry   
)

Definition at line 2544 of file entity_unittests.cc.

2544 {
2545 Entity entity;
2546 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2547 auto src_contents = std::make_shared<SolidColorContents>();
2548 src_contents->SetGeometry(
2549 Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000)));
2550 src_contents->SetColor(Color::Red());
2551
2552 auto dst_contents = std::make_shared<SolidColorContents>();
2553 dst_contents->SetGeometry(
2554 Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000)));
2555 dst_contents->SetColor(Color::Blue());
2556
2557 auto contents = ColorFilterContents::MakeBlend(
2558 BlendMode::kSourceOver, {FilterInput::Make(dst_contents, false),
2559 FilterInput::Make(src_contents, false)});
2560 entity.SetContents(std::move(contents));
2561 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2562}

◆ TEST_P() [307/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorFilterWithForegroundColorAdvancedBlend   
)

Definition at line 2377 of file entity_unittests.cc.

2377 {
2378 auto image = CreateTextureForFixture("boston.jpg");
2379 auto filter = ColorFilterContents::MakeBlend(
2380 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
2381
2382 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2383 Entity entity;
2384 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2385 Matrix::MakeTranslation({500, 300}) *
2386 Matrix::MakeScale(Vector2{0.5, 0.5}));
2387 entity.SetContents(filter);
2388 return entity.Render(context, pass);
2389 };
2390 ASSERT_TRUE(OpenPlaygroundHere(callback));
2391}

◆ TEST_P() [308/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorFilterWithForegroundColorClearBlend   
)

Definition at line 2393 of file entity_unittests.cc.

2393 {
2394 auto image = CreateTextureForFixture("boston.jpg");
2395 auto filter = ColorFilterContents::MakeBlend(
2396 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
2397
2398 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2399 Entity entity;
2400 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2401 Matrix::MakeTranslation({500, 300}) *
2402 Matrix::MakeScale(Vector2{0.5, 0.5}));
2403 entity.SetContents(filter);
2404 return entity.Render(context, pass);
2405 };
2406 ASSERT_TRUE(OpenPlaygroundHere(callback));
2407}

◆ TEST_P() [309/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorFilterWithForegroundColorDstBlend   
)

Definition at line 2425 of file entity_unittests.cc.

2425 {
2426 auto image = CreateTextureForFixture("boston.jpg");
2427 auto filter = ColorFilterContents::MakeBlend(
2428 BlendMode::kDestination, FilterInput::Make({image}), Color::Red());
2429
2430 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2431 Entity entity;
2432 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2433 Matrix::MakeTranslation({500, 300}) *
2434 Matrix::MakeScale(Vector2{0.5, 0.5}));
2435 entity.SetContents(filter);
2436 return entity.Render(context, pass);
2437 };
2438 ASSERT_TRUE(OpenPlaygroundHere(callback));
2439}

◆ TEST_P() [310/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorFilterWithForegroundColorSrcBlend   
)

Definition at line 2409 of file entity_unittests.cc.

2409 {
2410 auto image = CreateTextureForFixture("boston.jpg");
2411 auto filter = ColorFilterContents::MakeBlend(
2412 BlendMode::kSource, FilterInput::Make({image}), Color::Red());
2413
2414 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2415 Entity entity;
2416 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2417 Matrix::MakeTranslation({500, 300}) *
2418 Matrix::MakeScale(Vector2{0.5, 0.5}));
2419 entity.SetContents(filter);
2420 return entity.Render(context, pass);
2421 };
2422 ASSERT_TRUE(OpenPlaygroundHere(callback));
2423}

◆ TEST_P() [311/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorFilterWithForegroundColorSrcInBlend   
)

Definition at line 2441 of file entity_unittests.cc.

2441 {
2442 auto image = CreateTextureForFixture("boston.jpg");
2443 auto filter = ColorFilterContents::MakeBlend(
2444 BlendMode::kSourceIn, FilterInput::Make({image}), Color::Red());
2445
2446 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2447 Entity entity;
2448 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2449 Matrix::MakeTranslation({500, 300}) *
2450 Matrix::MakeScale(Vector2{0.5, 0.5}));
2451 entity.SetContents(filter);
2452 return entity.Render(context, pass);
2453 };
2454 ASSERT_TRUE(OpenPlaygroundHere(callback));
2455}

◆ TEST_P() [312/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorMatrixFilterCoverageIsCorrect   
)

Definition at line 1839 of file entity_unittests.cc.

1839 {
1840 // Set up a simple color background.
1841 auto fill = std::make_shared<SolidColorContents>();
1842 fill->SetGeometry(Geometry::MakeFillPath(
1843 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1844 fill->SetColor(Color::Coral());
1845
1846 // Set the color matrix filter.
1847 ColorMatrix matrix = {
1848 1, 1, 1, 1, 1, //
1849 1, 1, 1, 1, 1, //
1850 1, 1, 1, 1, 1, //
1851 1, 1, 1, 1, 1, //
1852 };
1853
1854 auto filter =
1855 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1856
1857 Entity e;
1858 e.SetTransform(Matrix());
1859
1860 // Confirm that the actual filter coverage matches the expected coverage.
1861 auto actual = filter->GetCoverage(e);
1862 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1863
1864 ASSERT_TRUE(actual.has_value());
1865 ASSERT_RECT_NEAR(actual.value(), expected);
1866}

◆ TEST_P() [313/435]

impeller::testing::TEST_P ( EntityTest  ,
ColorMatrixFilterEditable   
)

Definition at line 1868 of file entity_unittests.cc.

1868 {
1869 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1870 ASSERT_TRUE(bay_bridge);
1871
1872 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1873 // UI state.
1874 static ColorMatrix color_matrix = {
1875 1, 0, 0, 0, 0, //
1876 0, 3, 0, 0, 0, //
1877 0, 0, 1, 0, 0, //
1878 0, 0, 0, 1, 0, //
1879 };
1880 static float offset[2] = {500, 400};
1881 static float rotation = 0;
1882 static float scale[2] = {0.65, 0.65};
1883 static float skew[2] = {0, 0};
1884
1885 // Define the ImGui
1886 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1887 {
1888 std::string label = "##1";
1889 for (int i = 0; i < 20; i += 5) {
1890 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1891 &(color_matrix.array[i]), 5, nullptr, nullptr,
1892 "%.2f", 0);
1893 label[2]++;
1894 }
1895
1896 ImGui::SliderFloat2("Translation", &offset[0], 0,
1897 pass.GetRenderTargetSize().width);
1898 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1899 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1900 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1901 }
1902 ImGui::End();
1903
1904 // Set the color matrix filter.
1905 auto filter = ColorFilterContents::MakeColorMatrix(
1906 FilterInput::Make(bay_bridge), color_matrix);
1907
1908 // Define the entity with the color matrix filter.
1909 Entity entity;
1910 entity.SetTransform(
1911 Matrix::MakeScale(GetContentScale()) *
1912 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1913 Matrix::MakeRotationZ(Radians(rotation)) *
1914 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1915 Matrix::MakeSkew(skew[0], skew[1]) *
1916 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1917 entity.SetContents(filter);
1918 entity.Render(context, pass);
1919
1920 return true;
1921 };
1922
1923 ASSERT_TRUE(OpenPlaygroundHere(callback));
1924}
Scalar array[20]
Definition color.h:118

◆ TEST_P() [314/435]

impeller::testing::TEST_P ( EntityTest  ,
ConicalGradientContentsIsOpaque   
)

Definition at line 2485 of file entity_unittests.cc.

2485 {
2486 ConicalGradientContents contents;
2487 contents.SetColors({Color::CornflowerBlue()});
2488 ASSERT_FALSE(contents.IsOpaque());
2489 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2490 ASSERT_FALSE(contents.IsOpaque());
2491}
void SetColors(std::vector< Color > colors)
virtual bool IsOpaque() const
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
Definition contents.cc:53

◆ TEST_P() [315/435]

impeller::testing::TEST_P ( EntityTest  ,
ContentContextOptionsHasReasonableHashFunctions   
)

Definition at line 2660 of file entity_unittests.cc.

2660 {
2662 auto hash_a = ContentContextOptions::Hash{}(opts);
2663
2664 opts.blend_mode = BlendMode::kColorBurn;
2665 auto hash_b = ContentContextOptions::Hash{}(opts);
2666
2667 opts.has_depth_stencil_attachments = false;
2668 auto hash_c = ContentContextOptions::Hash{}(opts);
2669
2670 opts.primitive_type = PrimitiveType::kPoint;
2671 auto hash_d = ContentContextOptions::Hash{}(opts);
2672
2673 EXPECT_NE(hash_a, hash_b);
2674 EXPECT_NE(hash_b, hash_c);
2675 EXPECT_NE(hash_c, hash_d);
2676}

◆ TEST_P() [316/435]

impeller::testing::TEST_P ( EntityTest  ,
ContentsGetBoundsForEmptyPathReturnsNullopt   
)

Definition at line 1331 of file entity_unittests.cc.

1331 {
1332 Entity entity;
1333 entity.SetContents(std::make_shared<SolidColorContents>());
1334 ASSERT_FALSE(entity.GetCoverage().has_value());
1335}

◆ TEST_P() [317/435]

impeller::testing::TEST_P ( EntityTest  ,
CoverageForStrokePathWithNegativeValuesInTransform   
)

Definition at line 2457 of file entity_unittests.cc.

2457 {
2458 auto arrow_head = PathBuilder{}
2459 .MoveTo({50, 120})
2460 .LineTo({120, 190})
2461 .LineTo({190, 120})
2462 .TakePath();
2463 auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound,
2464 Join::kRound);
2465
2466 auto transform = Matrix::MakeTranslation({300, 300}) *
2467 Matrix::MakeRotationZ(Radians(kPiOver2));
2468 // Note that e[0][0] used to be tested here, but it was -epsilon solely
2469 // due to floating point inaccuracy in the transcendental trig functions.
2470 // e[1][0] is the intended negative value that we care about (-1.0) as it
2471 // comes from the rotation of pi/2.
2472 EXPECT_LT(transform.e[1][0], 0.0f);
2473 auto coverage = geometry->GetCoverage(transform);
2474 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2475}

◆ TEST_P() [318/435]

impeller::testing::TEST_P ( EntityTest  ,
CubicCurveAndOverlapTest   
)

Definition at line 591 of file entity_unittests.cc.

591 {
592 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
593 Path path =
595 .MoveTo({359.934, 96.6335})
596 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
597 {354.673, 96.8895})
598 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
599 {354.367, 96.9075})
600 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
601 {349.259, 97.2355})
602 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
603 {348.625, 97.2834})
604 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
605 {343.789, 97.6722})
606 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
607 {342.703, 97.7734})
608 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
609 {338.246, 98.207})
610 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
611 {336.612, 98.3894})
612 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
613 {332.623, 98.8476})
614 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
615 {332.237, 98.8982})
616 .LineTo({332.237, 102.601})
617 .LineTo({321.778, 102.601})
618 .LineTo({321.778, 100.382})
619 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
620 {321.161, 100.476})
621 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
622 {315.332, 101.479})
623 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
624 {315.301, 101.484})
625 .LineTo({310.017, 105.94})
626 .LineTo({309.779, 105.427})
627 .LineTo({314.403, 101.651})
628 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
629 {314.368, 101.658})
630 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
631 {308.846, 102.748})
632 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
633 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
634 {303.425, 103.936})
635 .LineTo({299.105, 107.578})
636 .LineTo({298.867, 107.065})
637 .LineTo({302.394, 104.185})
638 .LineTo({302.412, 104.171})
639 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
640 {299.344, 104.921})
641 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
642 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
643 {291.462, 106.979})
644 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
645 {290.471, 107.257})
646 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
647 {287.449, 108.139})
648 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
649 {284.536, 109.035})
650 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
651 {281.952, 109.859})
652 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
653 {279.633, 110.638})
654 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
655 {276.803, 111.607})
656 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
657 {276.672, 111.653})
658 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
659 {271.721, 113.463})
660 .LineTo({271.717, 113.449})
661 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
662 {270.963, 113.628})
663 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
664 {270.748, 113.682})
665 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
666 {269.839, 113.926})
667 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
668 {269.681, 113.972})
669 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
670 {268.756, 114.239})
671 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
672 {268.367, 114.354})
673 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
674 {267.752, 114.54})
675 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
676 {253.564, 119.252})
677 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
678 {253.538, 119.261})
679 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
680 {248.189, 121.131})
681 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
682 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
683 {245.975, 121.912})
684 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
685 {244.698, 122.364})
686 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
687 {242.794, 123.04})
688 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
689 {240.961, 123.693})
690 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
691 {240.052, 124.018})
692 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
693 .LineTo({237.164, 125.003})
694 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
695 {235.81, 125.538})
696 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
697 {234.592, 125.977})
698 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
699 {234.59, 125.977})
700 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
701 {192.381, 141.429})
702 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
703 .LineTo({360, 160})
704 .LineTo({360, 119.256})
705 .LineTo({360, 106.332})
706 .LineTo({360, 96.6307})
707 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
708 {359.934, 96.6335})
709 .Close()
710 .MoveTo({337.336, 124.143})
711 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
712 {338.903, 121.511})
713 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
714 {337.336, 124.143})
715 .Close()
716 .MoveTo({340.082, 121.849})
717 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
718 {340.046, 122.075})
719 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
720 {340.023, 122.177})
721 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
722 {339.952, 122.437})
723 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
724 {339.918, 122.544})
725 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
726 {339.75, 122.938})
727 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
728 {339.74, 122.955})
729 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
730 {339.501, 123.328})
731 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
732 {339.41, 123.438})
733 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
734 {339.145, 123.714})
735 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
736 {339.025, 123.821})
737 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
738 {338.539, 124.143})
739 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
740 {338.58, 123.626})
741 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
742 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
743 {338.704, 123.151})
744 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
745 {338.714, 123.117})
746 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
747 {338.905, 122.712})
748 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
749 {338.922, 122.682})
750 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
751 {339.155, 122.34})
752 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
753 {339.172, 122.319})
754 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
755 {339.425, 122.037})
756 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
757 {339.435, 122.027})
758 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
759 {340.106, 121.511})
760 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
761 {340.082, 121.849})
762 .Close()
763 .MoveTo({340.678, 113.245})
764 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
765 {340.135, 113.775})
766 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
767 {339.115, 114.151})
768 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
769 {336.448, 114.516})
770 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
771 {334.384, 114.513})
772 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
773 {333.605, 114.424})
774 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
775 {331.41, 113.883})
776 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
777 {330.672, 112.813})
778 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
779 {334.526, 113.833})
780 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
781 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
782 {332.76, 110.402})
783 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
784 {335.228, 113.395})
785 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
786 {335.661, 109.592})
787 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
788 {336.07, 113.389})
789 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
790 {338.563, 110.402})
791 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
792 {336.753, 113.784})
793 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
794 {336.796, 113.833})
795 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
796 {340.65, 112.813})
797 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
798 {340.678, 113.245})
799 .Close()
800 .MoveTo({346.357, 106.771})
801 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
802 {347.924, 104.139})
803 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
804 {346.357, 106.771})
805 .Close()
806 .MoveTo({347.56, 106.771})
807 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
808 {349.127, 104.139})
809 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
810 {347.56, 106.771})
811 .Close()
812 .TakePath();
813 Entity entity;
814 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
815 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
816 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
817}

◆ TEST_P() [319/435]

impeller::testing::TEST_P ( EntityTest  ,
CubicCurveTest   
)

Definition at line 523 of file entity_unittests.cc.

523 {
524 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
525 Path path =
527 .MoveTo({237.164, 125.003})
528 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
529 {235.81, 125.538})
530 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
531 {234.592, 125.977})
532 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
533 {234.59, 125.977})
534 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
535 {192.381, 141.429})
536 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
537 .Close()
538 .TakePath();
539 Entity entity;
540 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
541 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
542 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
543}

◆ TEST_P() [320/435]

impeller::testing::TEST_P ( EntityTest  ,
DecalSpecializationAppliedToMorphologyFilter   
)

Definition at line 2644 of file entity_unittests.cc.

2644 {
2645 auto content_context = GetContentContext();
2646 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2647 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2648 });
2649
2650 auto decal_supported = static_cast<Scalar>(
2651 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2652 std::vector<Scalar> expected_constants = {decal_supported};
2653 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2654 expected_constants);
2655}

◆ TEST_P() [321/435]

impeller::testing::TEST_P ( EntityTest  ,
DoesNotCullEntitiesByDefault   
)

Definition at line 1688 of file entity_unittests.cc.

1688 {
1689 auto fill = std::make_shared<SolidColorContents>();
1690 fill->SetColor(Color::CornflowerBlue());
1691 fill->SetGeometry(
1692 Geometry::MakeRect(Rect::MakeLTRB(-1000, -1000, -900, -900)));
1693
1694 Entity entity;
1695 entity.SetContents(fill);
1696
1697 // Even though the entity is offscreen, this should still render because we do
1698 // not compute the coverage intersection by default.
1699 EXPECT_TRUE(entity.ShouldRender(Rect::MakeLTRB(0, 0, 100, 100)));
1700}
bool ShouldRender(const std::optional< Rect > &clip_coverage) const
Definition entity.cc:82

◆ TEST_P() [322/435]

impeller::testing::TEST_P ( EntityTest  ,
DrawAtlasNoColor   
)

Definition at line 1417 of file entity_unittests.cc.

1417 {
1418 // Draws the image as four squares stiched together.
1419 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1420 auto size = atlas->GetSize();
1421 // Divide image into four quadrants.
1422 Scalar half_width = size.width / 2;
1423 Scalar half_height = size.height / 2;
1424 std::vector<Rect> texture_coordinates = {
1425 Rect::MakeLTRB(0, 0, half_width, half_height),
1426 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1427 Rect::MakeLTRB(0, half_height, half_width, size.height),
1428 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1429 // Position quadrants adjacent to eachother.
1430 std::vector<Matrix> transforms = {
1431 Matrix::MakeTranslation({0, 0, 0}),
1432 Matrix::MakeTranslation({half_width, 0, 0}),
1433 Matrix::MakeTranslation({0, half_height, 0}),
1434 Matrix::MakeTranslation({half_width, half_height, 0})};
1435 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1436
1437 contents->SetTransforms(std::move(transforms));
1438 contents->SetTextureCoordinates(std::move(texture_coordinates));
1439 contents->SetTexture(atlas);
1440 contents->SetBlendMode(BlendMode::kSource);
1441
1442 Entity e;
1443 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1444 e.SetContents(contents);
1445
1446 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1447}

◆ TEST_P() [323/435]

impeller::testing::TEST_P ( EntityTest  ,
DrawAtlasNoColorFullSize   
)

Definition at line 1593 of file entity_unittests.cc.

1593 {
1594 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1595 auto size = atlas->GetSize();
1596 std::vector<Rect> texture_coordinates = {
1597 Rect::MakeLTRB(0, 0, size.width, size.height)};
1598 std::vector<Matrix> transforms = {Matrix::MakeTranslation({0, 0, 0})};
1599 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1600
1601 contents->SetTransforms(std::move(transforms));
1602 contents->SetTextureCoordinates(std::move(texture_coordinates));
1603 contents->SetTexture(atlas);
1604 contents->SetBlendMode(BlendMode::kSource);
1605
1606 Entity e;
1607 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1608 e.SetContents(contents);
1609
1610 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1611}

◆ TEST_P() [324/435]

impeller::testing::TEST_P ( EntityTest  ,
DrawAtlasUsesProvidedCullRectForCoverage   
)

Definition at line 1520 of file entity_unittests.cc.

1520 {
1521 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1522 auto size = atlas->GetSize();
1523
1524 Scalar half_width = size.width / 2;
1525 Scalar half_height = size.height / 2;
1526 std::vector<Rect> texture_coordinates = {
1527 Rect::MakeLTRB(0, 0, half_width, half_height),
1528 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1529 Rect::MakeLTRB(0, half_height, half_width, size.height),
1530 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1531 std::vector<Matrix> transforms = {
1532 Matrix::MakeTranslation({0, 0, 0}),
1533 Matrix::MakeTranslation({half_width, 0, 0}),
1534 Matrix::MakeTranslation({0, half_height, 0}),
1535 Matrix::MakeTranslation({half_width, half_height, 0})};
1536
1537 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1538
1539 contents->SetTransforms(std::move(transforms));
1540 contents->SetTextureCoordinates(std::move(texture_coordinates));
1541 contents->SetTexture(atlas);
1542 contents->SetBlendMode(BlendMode::kSource);
1543
1544 auto transform = Matrix::MakeScale(GetContentScale());
1545 Entity e;
1546 e.SetTransform(transform);
1547 e.SetContents(contents);
1548
1549 ASSERT_EQ(contents->GetCoverage(e).value(),
1550 Rect::MakeSize(size).TransformBounds(transform));
1551
1552 contents->SetCullRect(Rect::MakeLTRB(0, 0, 10, 10));
1553
1554 ASSERT_EQ(contents->GetCoverage(e).value(),
1555 Rect::MakeLTRB(0, 0, 10, 10).TransformBounds(transform));
1556}

◆ TEST_P() [325/435]

impeller::testing::TEST_P ( EntityTest  ,
DrawAtlasWithColorAdvanced   
)

Definition at line 1449 of file entity_unittests.cc.

1449 {
1450 // Draws the image as four squares stiched together.
1451 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1452 auto size = atlas->GetSize();
1453 // Divide image into four quadrants.
1454 Scalar half_width = size.width / 2;
1455 Scalar half_height = size.height / 2;
1456 std::vector<Rect> texture_coordinates = {
1457 Rect::MakeLTRB(0, 0, half_width, half_height),
1458 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1459 Rect::MakeLTRB(0, half_height, half_width, size.height),
1460 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1461 // Position quadrants adjacent to eachother.
1462 std::vector<Matrix> transforms = {
1463 Matrix::MakeTranslation({0, 0, 0}),
1464 Matrix::MakeTranslation({half_width, 0, 0}),
1465 Matrix::MakeTranslation({0, half_height, 0}),
1466 Matrix::MakeTranslation({half_width, half_height, 0})};
1467 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1468 Color::Yellow()};
1469 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1470
1471 contents->SetTransforms(std::move(transforms));
1472 contents->SetTextureCoordinates(std::move(texture_coordinates));
1473 contents->SetTexture(atlas);
1474 contents->SetColors(colors);
1475 contents->SetBlendMode(BlendMode::kModulate);
1476
1477 Entity e;
1478 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1479 e.SetContents(contents);
1480
1481 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1482}

◆ TEST_P() [326/435]

impeller::testing::TEST_P ( EntityTest  ,
DrawAtlasWithColorSimple   
)

Definition at line 1484 of file entity_unittests.cc.

1484 {
1485 // Draws the image as four squares stiched together. Because blend modes
1486 // aren't implented this ends up as four solid color blocks.
1487 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1488 auto size = atlas->GetSize();
1489 // Divide image into four quadrants.
1490 Scalar half_width = size.width / 2;
1491 Scalar half_height = size.height / 2;
1492 std::vector<Rect> texture_coordinates = {
1493 Rect::MakeLTRB(0, 0, half_width, half_height),
1494 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1495 Rect::MakeLTRB(0, half_height, half_width, size.height),
1496 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1497 // Position quadrants adjacent to eachother.
1498 std::vector<Matrix> transforms = {
1499 Matrix::MakeTranslation({0, 0, 0}),
1500 Matrix::MakeTranslation({half_width, 0, 0}),
1501 Matrix::MakeTranslation({0, half_height, 0}),
1502 Matrix::MakeTranslation({half_width, half_height, 0})};
1503 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1504 Color::Yellow()};
1505 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1506
1507 contents->SetTransforms(std::move(transforms));
1508 contents->SetTextureCoordinates(std::move(texture_coordinates));
1509 contents->SetTexture(atlas);
1510 contents->SetColors(colors);
1511 contents->SetBlendMode(BlendMode::kSourceATop);
1512
1513 Entity e;
1514 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1515 e.SetContents(contents);
1516
1517 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1518}

◆ TEST_P() [327/435]

impeller::testing::TEST_P ( EntityTest  ,
DrawAtlasWithOpacity   
)

Definition at line 1558 of file entity_unittests.cc.

1558 {
1559 // Draws the image as four squares stiched together slightly
1560 // opaque
1561 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1562 auto size = atlas->GetSize();
1563 // Divide image into four quadrants.
1564 Scalar half_width = size.width / 2;
1565 Scalar half_height = size.height / 2;
1566 std::vector<Rect> texture_coordinates = {
1567 Rect::MakeLTRB(0, 0, half_width, half_height),
1568 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1569 Rect::MakeLTRB(0, half_height, half_width, size.height),
1570 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1571 // Position quadrants adjacent to eachother.
1572 std::vector<Matrix> transforms = {
1573 Matrix::MakeTranslation({0, 0, 0}),
1574 Matrix::MakeTranslation({half_width, 0, 0}),
1575 Matrix::MakeTranslation({0, half_height, 0}),
1576 Matrix::MakeTranslation({half_width, half_height, 0})};
1577
1578 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1579
1580 contents->SetTransforms(std::move(transforms));
1581 contents->SetTextureCoordinates(std::move(texture_coordinates));
1582 contents->SetTexture(atlas);
1583 contents->SetBlendMode(BlendMode::kSource);
1584 contents->SetAlpha(0.5);
1585
1586 Entity e;
1587 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1588 e.SetContents(contents);
1589
1590 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1591}

◆ TEST_P() [328/435]

impeller::testing::TEST_P ( EntityTest  ,
EntityPassCanMergeSubpassIntoParent   
)

Definition at line 187 of file entity_unittests.cc.

187 {
188 // Both a red and a blue box should appear if the pass merging has worked
189 // correctly.
190
191 EntityPass pass;
192 auto subpass = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
193 Rect::MakeLTRB(50, 50, 150, 150),
194 ContentBoundsPromise::kUnknown, true);
195 pass.AddSubpass(std::move(subpass));
196
197 Entity entity;
198 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
199 auto contents = std::make_unique<SolidColorContents>();
200 contents->SetGeometry(Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
201 contents->SetColor(Color::Blue());
202 entity.SetContents(std::move(contents));
203
204 pass.AddEntity(std::move(entity));
205
206 ASSERT_TRUE(OpenPlaygroundHere(pass));
207}
void AddEntity(Entity entity)
Add an entity to the current entity pass.
EntityPass * AddSubpass(std::unique_ptr< EntityPass > pass)
Appends a given pass as a subpass.
auto CreatePassWithRectPath(Rect rect, std::optional< Rect > bounds_hint, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, bool collapse=false)

◆ TEST_P() [329/435]

impeller::testing::TEST_P ( EntityTest  ,
EntityPassCoverageRespectsCoverageLimit   
)

Definition at line 209 of file entity_unittests.cc.

209 {
210 // Rect is drawn entirely in negative area.
211 auto pass = CreatePassWithRectPath(Rect::MakeLTRB(-200, -200, -100, -100),
212 std::nullopt);
213
214 // Without coverage limit.
215 {
216 auto pass_coverage = pass->GetElementsCoverage(std::nullopt);
217 ASSERT_TRUE(pass_coverage.has_value());
218 ASSERT_RECT_NEAR(pass_coverage.value(),
219 Rect::MakeLTRB(-200, -200, -100, -100));
220 }
221
222 // With limit that doesn't overlap.
223 {
224 auto pass_coverage =
225 pass->GetElementsCoverage(Rect::MakeLTRB(0, 0, 100, 100));
226 ASSERT_FALSE(pass_coverage.has_value());
227 }
228
229 // With limit that partially overlaps.
230 {
231 auto pass_coverage =
232 pass->GetElementsCoverage(Rect::MakeLTRB(-150, -150, 0, 0));
233 ASSERT_TRUE(pass_coverage.has_value());
234 ASSERT_RECT_NEAR(pass_coverage.value(),
235 Rect::MakeLTRB(-150, -150, -100, -100));
236 }
237}

◆ TEST_P() [330/435]

impeller::testing::TEST_P ( EntityTest  ,
EntityPassRespectsUntrustedSubpassBoundsLimit   
)

Definition at line 124 of file entity_unittests.cc.

124 {
125 EntityPass pass;
126
127 auto subpass0 = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
128 Rect::MakeLTRB(50, 50, 150, 150));
129 auto subpass1 = CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
130 Rect::MakeLTRB(800, 800, 900, 900));
131
132 auto subpass0_coverage =
133 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
134 ASSERT_TRUE(subpass0_coverage.has_value());
135 ASSERT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(50, 50, 100, 100));
136
137 auto subpass1_coverage =
138 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
139 ASSERT_TRUE(subpass1_coverage.has_value());
140 ASSERT_RECT_NEAR(subpass1_coverage.value(),
141 Rect::MakeLTRB(800, 800, 900, 900));
142
143 pass.AddSubpass(std::move(subpass0));
144 pass.AddSubpass(std::move(subpass1));
145
146 auto coverage = pass.GetElementsCoverage(std::nullopt);
147 ASSERT_TRUE(coverage.has_value());
148 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(50, 50, 900, 900));
149}
std::optional< Rect > GetSubpassCoverage(const EntityPass &subpass, std::optional< Rect > coverage_limit) const
Computes the coverage of a given subpass. This is used to determine the texture size of a given subpa...
std::optional< Rect > GetElementsCoverage(std::optional< Rect > coverage_limit) const

◆ TEST_P() [331/435]

impeller::testing::TEST_P ( EntityTest  ,
EntityPassTrustsSnugSubpassBoundsLimit   
)

Definition at line 151 of file entity_unittests.cc.

151 {
152 EntityPass pass;
153
154 auto subpass0 = //
155 CreatePassWithRectPath(Rect::MakeLTRB(10, 10, 90, 90),
156 Rect::MakeLTRB(5, 5, 95, 95),
157 ContentBoundsPromise::kContainsContents);
158 auto subpass1 = //
159 CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
160 Rect::MakeLTRB(495, 495, 1005, 1005),
161 ContentBoundsPromise::kContainsContents);
162
163 auto subpass0_coverage =
164 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
165 EXPECT_TRUE(subpass0_coverage.has_value());
166 // Result should be the overridden bounds
167 // (we lied about them being snug, but the property is respected)
168 EXPECT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(5, 5, 95, 95));
169
170 auto subpass1_coverage =
171 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
172 EXPECT_TRUE(subpass1_coverage.has_value());
173 // Result should be the overridden bounds
174 // (we lied about them being snug, but the property is respected)
175 EXPECT_RECT_NEAR(subpass1_coverage.value(),
176 Rect::MakeLTRB(495, 495, 1005, 1005));
177
178 pass.AddSubpass(std::move(subpass0));
179 pass.AddSubpass(std::move(subpass1));
180
181 auto coverage = pass.GetElementsCoverage(std::nullopt);
182 EXPECT_TRUE(coverage.has_value());
183 // This result should be the union of the overridden bounds
184 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(5, 5, 1005, 1005));
185}

◆ TEST_P() [332/435]

impeller::testing::TEST_P ( EntityTest  ,
FailOnValidationError   
)

Definition at line 2736 of file entity_unittests.cc.

2736 {
2737 if (GetParam() != PlaygroundBackend::kVulkan) {
2738 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2739 }
2740 EXPECT_DEATH(
2741 // The easiest way to trigger a validation error is to try to compile
2742 // a shader with an unsupported pixel format.
2743 GetContentContext()->GetBlendColorBurnPipeline({
2744 .color_attachment_pixel_format = PixelFormat::kUnknown,
2745 .has_depth_stencil_attachments = false,
2746 }),
2747 "");
2748}

◆ TEST_P() [333/435]

impeller::testing::TEST_P ( EntityTest  ,
FillPathGeometryGetPositionBufferReturnsExpectedMode   
)

Definition at line 2702 of file entity_unittests.cc.

2702 {
2704 testing::MockRenderPass mock_pass(GetContext(), target);
2705
2706 auto get_result = [this, &mock_pass](const Path& path) {
2707 auto geometry = Geometry::MakeFillPath(
2708 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2709 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2710 };
2711
2712 // Convex path
2713 {
2714 GeometryResult result =
2715 get_result(PathBuilder{}
2716 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
2717 .SetConvexity(Convexity::kConvex)
2718 .TakePath());
2719 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2720 }
2721
2722 // Concave path
2723 {
2724 Path path = PathBuilder{}
2725 .MoveTo({0, 0})
2726 .LineTo({100, 0})
2727 .LineTo({100, 100})
2728 .LineTo({50, 50})
2729 .Close()
2730 .TakePath();
2731 GeometryResult result = get_result(path);
2732 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2733 }
2734}

◆ TEST_P() [334/435]

impeller::testing::TEST_P ( EntityTest  ,
FilterCoverageRespectsCropRect   
)

Definition at line 239 of file entity_unittests.cc.

239 {
240 auto image = CreateTextureForFixture("boston.jpg");
241 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
242 FilterInput::Make({image}));
243
244 // Without the crop rect (default behavior).
245 {
246 auto actual = filter->GetCoverage({});
247 auto expected = Rect::MakeSize(image->GetSize());
248
249 ASSERT_TRUE(actual.has_value());
250 ASSERT_RECT_NEAR(actual.value(), expected);
251 }
252
253 // With the crop rect.
254 {
255 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
256 filter->SetCoverageHint(expected);
257 auto actual = filter->GetCoverage({});
258
259 ASSERT_TRUE(actual.has_value());
260 ASSERT_RECT_NEAR(actual.value(), expected);
261 }
262}

◆ TEST_P() [335/435]

impeller::testing::TEST_P ( EntityTest  ,
Filters   
)

Definition at line 1023 of file entity_unittests.cc.

1023 {
1024 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1025 auto boston = CreateTextureForFixture("boston.jpg");
1026 auto kalimba = CreateTextureForFixture("kalimba.jpg");
1027 ASSERT_TRUE(bridge && boston && kalimba);
1028
1029 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1030 auto fi_bridge = FilterInput::Make(bridge);
1031 auto fi_boston = FilterInput::Make(boston);
1032 auto fi_kalimba = FilterInput::Make(kalimba);
1033
1034 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
1035 BlendMode::kModulate, {fi_kalimba, fi_boston});
1036
1037 auto blend1 = ColorFilterContents::MakeBlend(
1038 BlendMode::kScreen,
1039 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
1040
1041 Entity entity;
1042 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1043 Matrix::MakeTranslation({500, 300}) *
1044 Matrix::MakeScale(Vector2{0.5, 0.5}));
1045 entity.SetContents(blend1);
1046 return entity.Render(context, pass);
1047 };
1048 ASSERT_TRUE(OpenPlaygroundHere(callback));
1049}

◆ TEST_P() [336/435]

impeller::testing::TEST_P ( EntityTest  ,
GaussianBlurFilter   
)

Definition at line 1051 of file entity_unittests.cc.

1051 {
1052 auto boston =
1053 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
1054 ASSERT_TRUE(boston);
1055
1056 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1057 const char* input_type_names[] = {"Texture", "Solid Color"};
1058 const char* blur_type_names[] = {"Image blur", "Mask blur"};
1059 const char* pass_variation_names[] = {"New"};
1060 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
1061 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1062 const FilterContents::BlurStyle blur_styles[] = {
1063 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
1064 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
1065 const Entity::TileMode tile_modes[] = {
1066 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
1067 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
1068
1069 // UI state.
1070 static int selected_input_type = 0;
1071 static Color input_color = Color::Black();
1072 static int selected_blur_type = 0;
1073 static int selected_pass_variation = 0;
1074 static bool combined_sigma = false;
1075 static float blur_amount_coarse[2] = {0, 0};
1076 static float blur_amount_fine[2] = {10, 10};
1077 static int selected_blur_style = 0;
1078 static int selected_tile_mode = 3;
1079 static Color cover_color(1, 0, 0, 0.2);
1080 static Color bounds_color(0, 1, 0, 0.1);
1081 static float offset[2] = {500, 400};
1082 static float rotation = 0;
1083 static float scale[2] = {0.65, 0.65};
1084 static float skew[2] = {0, 0};
1085 static float path_rect[4] = {0, 0,
1086 static_cast<float>(boston->GetSize().width),
1087 static_cast<float>(boston->GetSize().height)};
1088
1089 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1090 {
1091 ImGui::Combo("Input type", &selected_input_type, input_type_names,
1092 sizeof(input_type_names) / sizeof(char*));
1093 if (selected_input_type == 0) {
1094 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1095 } else {
1096 ImGui::ColorEdit4("Input color",
1097 reinterpret_cast<float*>(&input_color));
1098 }
1099 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
1100 sizeof(blur_type_names) / sizeof(char*));
1101 if (selected_blur_type == 0) {
1102 ImGui::Combo("Pass variation", &selected_pass_variation,
1103 pass_variation_names,
1104 sizeof(pass_variation_names) / sizeof(char*));
1105 }
1106 ImGui::Checkbox("Combined sigma", &combined_sigma);
1107 if (combined_sigma) {
1108 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1109 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
1110 blur_amount_coarse[1] = blur_amount_coarse[0];
1111 blur_amount_fine[1] = blur_amount_fine[0];
1112 } else {
1113 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1114 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1115 }
1116 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1117 sizeof(blur_style_names) / sizeof(char*));
1118 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1119 sizeof(tile_mode_names) / sizeof(char*));
1120 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1121 ImGui::ColorEdit4("Bounds color",
1122 reinterpret_cast<float*>(&bounds_color));
1123 ImGui::SliderFloat2("Translation", offset, 0,
1124 pass.GetRenderTargetSize().width);
1125 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1126 ImGui::SliderFloat2("Scale", scale, 0, 3);
1127 ImGui::SliderFloat2("Skew", skew, -3, 3);
1128 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1129 }
1130 ImGui::End();
1131
1132 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1133 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1134
1135 std::shared_ptr<Contents> input;
1136 Size input_size;
1137
1138 auto input_rect =
1139 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1140 if (selected_input_type == 0) {
1141 auto texture = std::make_shared<TextureContents>();
1142 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1143 texture->SetDestinationRect(input_rect);
1144 texture->SetTexture(boston);
1145 texture->SetOpacity(input_color.alpha);
1146
1147 input = texture;
1148 input_size = input_rect.GetSize();
1149 } else {
1150 auto fill = std::make_shared<SolidColorContents>();
1151 fill->SetColor(input_color);
1152 fill->SetGeometry(
1153 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath()));
1154
1155 input = fill;
1156 input_size = input_rect.GetSize();
1157 }
1158
1159 std::shared_ptr<FilterContents> blur;
1160 switch (selected_pass_variation) {
1161 case 0:
1162 blur = std::make_shared<GaussianBlurFilterContents>(
1163 blur_sigma_x.sigma, blur_sigma_y.sigma,
1164 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1165 /*geometry=*/nullptr);
1166 blur->SetInputs({FilterInput::Make(input)});
1167 break;
1168 case 1:
1169 blur = FilterContents::MakeGaussianBlur(
1170 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1171 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1172 break;
1173 };
1174 FML_CHECK(blur);
1175
1176 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1177 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1178 blur_styles[selected_blur_style]);
1179
1180 auto ctm = Matrix::MakeScale(GetContentScale()) *
1181 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1182 Matrix::MakeRotationZ(Radians(rotation)) *
1183 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1184 Matrix::MakeSkew(skew[0], skew[1]) *
1185 Matrix::MakeTranslation(-Point(input_size) / 2);
1186
1187 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1188
1189 Entity entity;
1190 entity.SetContents(target_contents);
1191 entity.SetTransform(ctm);
1192
1193 entity.Render(context, pass);
1194
1195 // Renders a red "cover" rectangle that shows the original position of the
1196 // unfiltered input.
1197 Entity cover_entity;
1198 cover_entity.SetContents(SolidColorContents::Make(
1199 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1200 cover_entity.SetTransform(ctm);
1201
1202 cover_entity.Render(context, pass);
1203
1204 // Renders a green bounding rect of the target filter.
1205 Entity bounds_entity;
1206 std::optional<Rect> target_contents_coverage =
1207 target_contents->GetCoverage(entity);
1208 if (target_contents_coverage.has_value()) {
1209 bounds_entity.SetContents(SolidColorContents::Make(
1210 PathBuilder{}
1211 .AddRect(target_contents->GetCoverage(entity).value())
1212 .TakePath(),
1213 bounds_color));
1214 bounds_entity.SetTransform(Matrix());
1215
1216 bounds_entity.Render(context, pass);
1217 }
1218
1219 return true;
1220 };
1221 ASSERT_TRUE(OpenPlaygroundHere(callback));
1222}

◆ TEST_P() [337/435]

impeller::testing::TEST_P ( EntityTest  ,
GeometryBoundsAreTransformed   
)

Definition at line 292 of file entity_unittests.cc.

292 {
293 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
294 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
295
296 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
297 Rect::MakeXYWH(200, 200, 200, 200));
298}

◆ TEST_P() [338/435]

impeller::testing::TEST_P ( EntityTest  ,
InheritOpacityTest   
)

Definition at line 2307 of file entity_unittests.cc.

2307 {
2308 Entity entity;
2309
2310 // Texture contents can always accept opacity.
2311 auto texture_contents = std::make_shared<TextureContents>();
2312 texture_contents->SetOpacity(0.5);
2313 ASSERT_TRUE(texture_contents->CanInheritOpacity(entity));
2314
2315 texture_contents->SetInheritedOpacity(0.5);
2316 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2317 texture_contents->SetInheritedOpacity(0.5);
2318 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2319
2320 // Solid color contents can accept opacity if their geometry
2321 // doesn't overlap.
2322 auto solid_color = std::make_shared<SolidColorContents>();
2323 solid_color->SetGeometry(
2324 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2325 solid_color->SetColor(Color::Blue().WithAlpha(0.5));
2326
2327 ASSERT_TRUE(solid_color->CanInheritOpacity(entity));
2328
2329 solid_color->SetInheritedOpacity(0.5);
2330 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2331 solid_color->SetInheritedOpacity(0.5);
2332 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2333
2334 // Color source contents can accept opacity if their geometry
2335 // doesn't overlap.
2336 auto tiled_texture = std::make_shared<TiledTextureContents>();
2337 tiled_texture->SetGeometry(
2338 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2339 tiled_texture->SetOpacityFactor(0.5);
2340
2341 ASSERT_TRUE(tiled_texture->CanInheritOpacity(entity));
2342
2343 tiled_texture->SetInheritedOpacity(0.5);
2344 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2345 tiled_texture->SetInheritedOpacity(0.5);
2346 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2347
2348 // Text contents can accept opacity if the text frames do not
2349 // overlap
2351 auto blob = SkTextBlob::MakeFromString("A", font);
2353 auto lazy_glyph_atlas =
2354 std::make_shared<LazyGlyphAtlas>(TypographerContextSkia::Make());
2355 lazy_glyph_atlas->AddTextFrame(*frame, 1.0f);
2356
2357 auto text_contents = std::make_shared<TextContents>();
2358 text_contents->SetTextFrame(frame);
2359 text_contents->SetColor(Color::Blue().WithAlpha(0.5));
2360
2361 ASSERT_TRUE(text_contents->CanInheritOpacity(entity));
2362
2363 text_contents->SetInheritedOpacity(0.5);
2364 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2365 text_contents->SetInheritedOpacity(0.5);
2366 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2367
2368 // Clips and restores trivially accept opacity.
2369 ASSERT_TRUE(ClipContents().CanInheritOpacity(entity));
2370 ASSERT_TRUE(ClipRestoreContents().CanInheritOpacity(entity));
2371
2372 // Runtime effect contents can't accept opacity.
2373 auto runtime_effect = std::make_shared<RuntimeEffectContents>();
2374 ASSERT_FALSE(runtime_effect->CanInheritOpacity(entity));
2375}
SkFont CreateTestFontOfSize(SkScalar scalar)

◆ TEST_P() [339/435]

impeller::testing::TEST_P ( EntityTest  ,
LinearGradientContentsIsOpaque   
)

Definition at line 2493 of file entity_unittests.cc.

2493 {
2494 LinearGradientContents contents;
2495 contents.SetColors({Color::CornflowerBlue()});
2496 ASSERT_TRUE(contents.IsOpaque());
2497 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2498 ASSERT_FALSE(contents.IsOpaque());
2499 contents.SetColors({Color::CornflowerBlue()});
2500 contents.SetTileMode(Entity::TileMode::kDecal);
2501 ASSERT_FALSE(contents.IsOpaque());
2502}
bool IsOpaque() const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
void SetTileMode(Entity::TileMode tile_mode)
void SetColors(std::vector< Color > colors)

◆ TEST_P() [340/435]

impeller::testing::TEST_P ( EntityTest  ,
LinearToSrgbFilter   
)

Definition at line 1947 of file entity_unittests.cc.

1947 {
1948 auto image = CreateTextureForFixture("kalimba.jpg");
1949 ASSERT_TRUE(image);
1950
1951 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1952 auto filtered =
1953 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1954
1955 // Define the entity that will serve as the control image as a Gaussian blur
1956 // filter with no filter at all.
1957 Entity entity_left;
1958 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1959 Matrix::MakeTranslation({100, 300}) *
1960 Matrix::MakeScale(Vector2{0.5, 0.5}));
1961 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1962 Sigma{0}, Sigma{0});
1963 entity_left.SetContents(unfiltered);
1964
1965 // Define the entity that will be filtered from linear to sRGB.
1966 Entity entity_right;
1967 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1968 Matrix::MakeTranslation({500, 300}) *
1969 Matrix::MakeScale(Vector2{0.5, 0.5}));
1970 entity_right.SetContents(filtered);
1971 return entity_left.Render(context, pass) &&
1972 entity_right.Render(context, pass);
1973 };
1974
1975 ASSERT_TRUE(OpenPlaygroundHere(callback));
1976}

◆ TEST_P() [341/435]

impeller::testing::TEST_P ( EntityTest  ,
LinearToSrgbFilterCoverageIsCorrect   
)

Definition at line 1926 of file entity_unittests.cc.

1926 {
1927 // Set up a simple color background.
1928 auto fill = std::make_shared<SolidColorContents>();
1929 fill->SetGeometry(Geometry::MakeFillPath(
1930 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1931 fill->SetColor(Color::MintCream());
1932
1933 auto filter =
1934 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1935
1936 Entity e;
1937 e.SetTransform(Matrix());
1938
1939 // Confirm that the actual filter coverage matches the expected coverage.
1940 auto actual = filter->GetCoverage(e);
1941 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1942
1943 ASSERT_TRUE(actual.has_value());
1944 ASSERT_RECT_NEAR(actual.value(), expected);
1945}

◆ TEST_P() [342/435]

impeller::testing::TEST_P ( EntityTest  ,
MorphologyFilter   
)

Definition at line 1224 of file entity_unittests.cc.

1224 {
1225 auto boston = CreateTextureForFixture("boston.jpg");
1226 ASSERT_TRUE(boston);
1227
1228 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1229 const char* morphology_type_names[] = {"Dilate", "Erode"};
1230 const FilterContents::MorphType morphology_types[] = {
1231 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1232 static Color input_color = Color::Black();
1233 // UI state.
1234 static int selected_morphology_type = 0;
1235 static float radius[2] = {20, 20};
1236 static Color cover_color(1, 0, 0, 0.2);
1237 static Color bounds_color(0, 1, 0, 0.1);
1238 static float offset[2] = {500, 400};
1239 static float rotation = 0;
1240 static float scale[2] = {0.65, 0.65};
1241 static float skew[2] = {0, 0};
1242 static float path_rect[4] = {0, 0,
1243 static_cast<float>(boston->GetSize().width),
1244 static_cast<float>(boston->GetSize().height)};
1245 static float effect_transform_scale = 1;
1246
1247 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1248 {
1249 ImGui::Combo("Morphology type", &selected_morphology_type,
1250 morphology_type_names,
1251 sizeof(morphology_type_names) / sizeof(char*));
1252 ImGui::SliderFloat2("Radius", radius, 0, 200);
1253 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1254 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1255 ImGui::ColorEdit4("Bounds color",
1256 reinterpret_cast<float*>(&bounds_color));
1257 ImGui::SliderFloat2("Translation", offset, 0,
1258 pass.GetRenderTargetSize().width);
1259 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1260 ImGui::SliderFloat2("Scale", scale, 0, 3);
1261 ImGui::SliderFloat2("Skew", skew, -3, 3);
1262 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1263 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1264 3);
1265 }
1266 ImGui::End();
1267
1268 std::shared_ptr<Contents> input;
1269 Size input_size;
1270
1271 auto input_rect =
1272 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1273 auto texture = std::make_shared<TextureContents>();
1274 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1275 texture->SetDestinationRect(input_rect);
1276 texture->SetTexture(boston);
1277 texture->SetOpacity(input_color.alpha);
1278
1279 input = texture;
1280 input_size = input_rect.GetSize();
1281
1282 auto contents = FilterContents::MakeMorphology(
1283 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1284 morphology_types[selected_morphology_type]);
1285 contents->SetEffectTransform(Matrix::MakeScale(
1286 Vector2{effect_transform_scale, effect_transform_scale}));
1287
1288 auto ctm = Matrix::MakeScale(GetContentScale()) *
1289 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1290 Matrix::MakeRotationZ(Radians(rotation)) *
1291 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1292 Matrix::MakeSkew(skew[0], skew[1]) *
1293 Matrix::MakeTranslation(-Point(input_size) / 2);
1294
1295 Entity entity;
1296 entity.SetContents(contents);
1297 entity.SetTransform(ctm);
1298
1299 entity.Render(context, pass);
1300
1301 // Renders a red "cover" rectangle that shows the original position of the
1302 // unfiltered input.
1303 Entity cover_entity;
1304 cover_entity.SetContents(SolidColorContents::Make(
1305 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1306 cover_entity.SetTransform(ctm);
1307
1308 cover_entity.Render(context, pass);
1309
1310 // Renders a green bounding rect of the target filter.
1311 Entity bounds_entity;
1312 bounds_entity.SetContents(SolidColorContents::Make(
1313 PathBuilder{}.AddRect(contents->GetCoverage(entity).value()).TakePath(),
1314 bounds_color));
1315 bounds_entity.SetTransform(Matrix());
1316
1317 bounds_entity.Render(context, pass);
1318
1319 return true;
1320 };
1321 ASSERT_TRUE(OpenPlaygroundHere(callback));
1322}

◆ TEST_P() [343/435]

impeller::testing::TEST_P ( EntityTest  ,
PointFieldGeometryCoverage   
)

Definition at line 2536 of file entity_unittests.cc.

2536 {
2537 std::vector<Point> points = {{10, 20}, {100, 200}};
2538 auto geometry = Geometry::MakePointField(points, 5.0, false);
2539 ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2540 ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2541 Rect::MakeLTRB(35, 15, 135, 205));
2542}

◆ TEST_P() [344/435]

impeller::testing::TEST_P ( EntityTest  ,
RadialGradientContentsIsOpaque   
)

Definition at line 2504 of file entity_unittests.cc.

2504 {
2505 RadialGradientContents contents;
2506 contents.SetColors({Color::CornflowerBlue()});
2507 ASSERT_TRUE(contents.IsOpaque());
2508 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2509 ASSERT_FALSE(contents.IsOpaque());
2510 contents.SetColors({Color::CornflowerBlue()});
2511 contents.SetTileMode(Entity::TileMode::kDecal);
2512 ASSERT_FALSE(contents.IsOpaque());
2513}
void SetTileMode(Entity::TileMode tile_mode)
bool IsOpaque() const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
void SetColors(std::vector< Color > colors)

◆ TEST_P() [345/435]

impeller::testing::TEST_P ( EntityTest  ,
RRectShadowTest   
)

Definition at line 1786 of file entity_unittests.cc.

1786 {
1787 auto callback = [&](ContentContext& context, RenderPass& pass) {
1788 static Color color = Color::Red();
1789 static float corner_radius = 100;
1790 static float blur_radius = 100;
1791 static bool show_coverage = false;
1792 static Color coverage_color = Color::Green().WithAlpha(0.2);
1793
1794 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1795 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1796 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1797 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1798 ImGui::Checkbox("Show coverage", &show_coverage);
1799 if (show_coverage) {
1800 ImGui::ColorEdit4("Coverage color",
1801 reinterpret_cast<Scalar*>(&coverage_color));
1802 }
1803 ImGui::End();
1804
1805 static PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1806 static PlaygroundPoint bottom_right_point(Point(600, 400), 30,
1807 Color::White());
1808 auto [top_left, bottom_right] =
1809 DrawPlaygroundLine(top_left_point, bottom_right_point);
1810 auto rect =
1811 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1812
1813 auto contents = std::make_unique<SolidRRectBlurContents>();
1814 contents->SetRRect(rect, {corner_radius, corner_radius});
1815 contents->SetColor(color);
1816 contents->SetSigma(Radius(blur_radius));
1817
1818 Entity entity;
1819 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1820 entity.SetContents(std::move(contents));
1821 entity.Render(context, pass);
1822
1823 auto coverage = entity.GetCoverage();
1824 if (show_coverage && coverage.has_value()) {
1825 auto bounds_contents = std::make_unique<SolidColorContents>();
1826 bounds_contents->SetGeometry(Geometry::MakeFillPath(
1827 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
1828 bounds_contents->SetColor(coverage_color.Premultiply());
1829 Entity bounds_entity;
1830 bounds_entity.SetContents(std::move(bounds_contents));
1831 bounds_entity.Render(context, pass);
1832 }
1833
1834 return true;
1835 };
1836 ASSERT_TRUE(OpenPlaygroundHere(callback));
1837}
constexpr Color Premultiply() const
Definition color.h:214

◆ TEST_P() [346/435]

impeller::testing::TEST_P ( EntityTest  ,
RuntimeEffect   
)

Definition at line 2131 of file entity_unittests.cc.

2131 {
2132 auto runtime_stages =
2133 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2134 auto runtime_stage =
2135 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2136 ASSERT_TRUE(runtime_stage);
2137 ASSERT_TRUE(runtime_stage->IsDirty());
2138
2139 bool expect_dirty = true;
2140 Pipeline<PipelineDescriptor>* first_pipeline;
2141 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2142 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
2143
2144 auto contents = std::make_shared<RuntimeEffectContents>();
2145 contents->SetGeometry(Geometry::MakeCover());
2146 contents->SetRuntimeStage(runtime_stage);
2147
2148 struct FragUniforms {
2149 Vector2 iResolution;
2150 Scalar iTime;
2151 } frag_uniforms = {
2152 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2153 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2154 };
2155 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2156 uniform_data->resize(sizeof(FragUniforms));
2157 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2158 contents->SetUniformData(uniform_data);
2159
2160 Entity entity;
2161 entity.SetContents(contents);
2162 bool result = contents->Render(context, entity, pass);
2163
2164 if (expect_dirty) {
2165 EXPECT_NE(first_pipeline, pass.GetCommands().back().pipeline.get());
2166 first_pipeline = pass.GetCommands().back().pipeline.get();
2167 } else {
2168 EXPECT_EQ(pass.GetCommands().back().pipeline.get(), first_pipeline);
2169 }
2170
2171 expect_dirty = false;
2172 return result;
2173 };
2174
2175 // Simulate some renders and hot reloading of the shader.
2176 auto content_context = GetContentContext();
2177 {
2179 content_context->GetRenderTargetCache()->CreateOffscreen(
2180 *content_context->GetContext(), {1, 1}, 1u);
2181
2182 testing::MockRenderPass mock_pass(GetContext(), target);
2183 callback(*content_context, mock_pass);
2184 callback(*content_context, mock_pass);
2185
2186 // Dirty the runtime stage.
2187 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2188 runtime_stage =
2189 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2190
2191 ASSERT_TRUE(runtime_stage->IsDirty());
2192 expect_dirty = true;
2193
2194 callback(*content_context, mock_pass);
2195 }
2196}
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition pipeline.h:49

◆ TEST_P() [347/435]

impeller::testing::TEST_P ( EntityTest  ,
RuntimeEffectCanPrecache   
)

Definition at line 2245 of file entity_unittests.cc.

2245 {
2246 auto runtime_stages =
2247 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2248 auto runtime_stage =
2249 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2250 ASSERT_TRUE(runtime_stage);
2251 ASSERT_TRUE(runtime_stage->IsDirty());
2252
2253 auto contents = std::make_shared<RuntimeEffectContents>();
2254 contents->SetRuntimeStage(runtime_stage);
2255
2256 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
2257}

◆ TEST_P() [348/435]

impeller::testing::TEST_P ( EntityTest  ,
RuntimeEffectCanSuccessfullyRender   
)

Definition at line 2198 of file entity_unittests.cc.

2198 {
2199 auto runtime_stages =
2200 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2201 auto runtime_stage =
2202 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2203 ASSERT_TRUE(runtime_stage);
2204 ASSERT_TRUE(runtime_stage->IsDirty());
2205
2206 auto contents = std::make_shared<RuntimeEffectContents>();
2207 contents->SetGeometry(Geometry::MakeCover());
2208
2209 contents->SetRuntimeStage(runtime_stage);
2210
2211 struct FragUniforms {
2212 Vector2 iResolution;
2213 Scalar iTime;
2214 } frag_uniforms = {
2215 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2216 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2217 };
2218 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2219 uniform_data->resize(sizeof(FragUniforms));
2220 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2221 contents->SetUniformData(uniform_data);
2222
2223 Entity entity;
2224 entity.SetContents(contents);
2225
2226 // Create a render target with a depth-stencil, similar to how EntityPass
2227 // does.
2228 RenderTarget target =
2229 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
2230 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
2231 "RuntimeEffect Texture");
2232 testing::MockRenderPass pass(GetContext(), target);
2233
2234 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
2235 ASSERT_EQ(pass.GetCommands().size(), 1u);
2236 const auto& command = pass.GetCommands()[0];
2237 ASSERT_TRUE(command.pipeline->GetDescriptor()
2238 .GetDepthStencilAttachmentDescriptor()
2239 .has_value());
2240 ASSERT_TRUE(command.pipeline->GetDescriptor()
2241 .GetFrontStencilAttachmentDescriptor()
2242 .has_value());
2243}
list command
Definition valgrind.py:24

◆ TEST_P() [349/435]

impeller::testing::TEST_P ( EntityTest  ,
RuntimeEffectSetsRightSizeWhenUniformIsStruct   
)

Definition at line 2259 of file entity_unittests.cc.

2259 {
2260 if (GetBackend() != PlaygroundBackend::kVulkan) {
2261 GTEST_SKIP() << "Test only applies to Vulkan";
2262 }
2263
2264 auto runtime_stages =
2265 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2266 auto runtime_stage =
2267 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2268 ASSERT_TRUE(runtime_stage);
2269 ASSERT_TRUE(runtime_stage->IsDirty());
2270
2271 auto contents = std::make_shared<RuntimeEffectContents>();
2272 contents->SetGeometry(Geometry::MakeCover());
2273 contents->SetRuntimeStage(runtime_stage);
2274
2275 struct FragUniforms {
2276 Vector2 iResolution;
2277 Scalar iTime;
2278 } frag_uniforms = {
2279 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2280 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2281 };
2282 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2283 uniform_data->resize(sizeof(FragUniforms));
2284 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2285 contents->SetUniformData(uniform_data);
2286
2287 Entity entity;
2288 entity.SetContents(contents);
2289
2290 auto context = GetContentContext();
2291 RenderTarget target = context->GetRenderTargetCache()->CreateOffscreen(
2292 *context->GetContext(), {1, 1}, 1u);
2293
2294 testing::MockRenderPass pass(GetContext(), target);
2295 ASSERT_TRUE(contents->Render(*context, entity, pass));
2296 ASSERT_EQ(pass.GetCommands().size(), 1u);
2297 const auto& command = pass.GetCommands()[0];
2298 ASSERT_EQ(command.fragment_bindings.buffers.size(), 1u);
2299 // 16 bytes:
2300 // 8 bytes for iResolution
2301 // 4 bytes for iTime
2302 // 4 bytes padding
2303 EXPECT_EQ(command.fragment_bindings.buffers[0].view.resource.range.length,
2304 16u);
2305}

◆ TEST_P() [350/435]

impeller::testing::TEST_P ( EntityTest  ,
SetBlendMode   
)

Definition at line 1324 of file entity_unittests.cc.

1324 {
1325 Entity entity;
1326 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSourceOver);
1327 entity.SetBlendMode(BlendMode::kClear);
1328 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1329}
BlendMode GetBlendMode() const
Definition entity.cc:119

◆ TEST_P() [351/435]

impeller::testing::TEST_P ( EntityTest  ,
SolidColorContentsIsOpaque   
)

Definition at line 2477 of file entity_unittests.cc.

2477 {
2478 SolidColorContents contents;
2479 contents.SetColor(Color::CornflowerBlue());
2480 ASSERT_TRUE(contents.IsOpaque());
2481 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2482 ASSERT_FALSE(contents.IsOpaque());
2483}
bool IsOpaque() const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...

◆ TEST_P() [352/435]

impeller::testing::TEST_P ( EntityTest  ,
SolidColorContentsStrokeSetMiterLimit   
)

Definition at line 841 of file entity_unittests.cc.

841 {
842 {
843 auto geometry = Geometry::MakeStrokePath(Path{});
844 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
845 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
846 }
847
848 {
849 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/8.0);
850 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
851 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
852 }
853
854 {
855 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/-1.0);
856 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
857 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
858 }
859}
A geometry that is created from a stroked path object.

◆ TEST_P() [353/435]

impeller::testing::TEST_P ( EntityTest  ,
SolidColorContentsStrokeSetStrokeCapsAndJoins   
)

Definition at line 819 of file entity_unittests.cc.

819 {
820 {
821 auto geometry = Geometry::MakeStrokePath(Path{});
822 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
823 // Defaults.
824 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
825 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
826 }
827
828 {
829 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
830 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
831 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
832 }
833
834 {
835 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
836 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
837 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
838 }
839}

◆ TEST_P() [354/435]

impeller::testing::TEST_P ( EntityTest  ,
SolidFillCoverageIsCorrect   
)

Definition at line 1613 of file entity_unittests.cc.

1613 {
1614 // No transform
1615 {
1616 auto fill = std::make_shared<SolidColorContents>();
1617 fill->SetColor(Color::CornflowerBlue());
1618 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1619 fill->SetGeometry(
1620 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath()));
1621
1622 auto coverage = fill->GetCoverage({});
1623 ASSERT_TRUE(coverage.has_value());
1624 ASSERT_RECT_NEAR(coverage.value(), expected);
1625 }
1626
1627 // Entity transform
1628 {
1629 auto fill = std::make_shared<SolidColorContents>();
1630 fill->SetColor(Color::CornflowerBlue());
1631 fill->SetGeometry(Geometry::MakeFillPath(
1632 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1633
1634 Entity entity;
1635 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1636 entity.SetContents(std::move(fill));
1637
1638 auto coverage = entity.GetCoverage();
1639 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1640 ASSERT_TRUE(coverage.has_value());
1641 ASSERT_RECT_NEAR(coverage.value(), expected);
1642 }
1643
1644 // No coverage for fully transparent colors
1645 {
1646 auto fill = std::make_shared<SolidColorContents>();
1647 fill->SetColor(Color::WhiteTransparent());
1648 fill->SetGeometry(Geometry::MakeFillPath(
1649 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1650
1651 auto coverage = fill->GetCoverage({});
1652 ASSERT_FALSE(coverage.has_value());
1653 }
1654}

◆ TEST_P() [355/435]

impeller::testing::TEST_P ( EntityTest  ,
SolidFillShouldRenderIsCorrect   
)

Definition at line 1656 of file entity_unittests.cc.

1656 {
1657 // No path.
1658 {
1659 auto fill = std::make_shared<SolidColorContents>();
1660 fill->SetColor(Color::CornflowerBlue());
1661 ASSERT_FALSE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1662 ASSERT_FALSE(
1663 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1664 }
1665
1666 // With path.
1667 {
1668 auto fill = std::make_shared<SolidColorContents>();
1669 fill->SetColor(Color::CornflowerBlue());
1670 fill->SetGeometry(Geometry::MakeFillPath(
1671 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1672 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1673 ASSERT_FALSE(
1674 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1675 }
1676
1677 // With paint cover.
1678 {
1679 auto fill = std::make_shared<SolidColorContents>();
1680 fill->SetColor(Color::CornflowerBlue());
1681 fill->SetGeometry(Geometry::MakeCover());
1682 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1683 ASSERT_TRUE(
1684 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1685 }
1686}

◆ TEST_P() [356/435]

impeller::testing::TEST_P ( EntityTest  ,
SolidStrokeCoverageIsCorrect   
)

Definition at line 1337 of file entity_unittests.cc.

1337 {
1338 {
1339 auto geometry = Geometry::MakeStrokePath(
1340 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1341 Cap::kButt, Join::kBevel);
1342
1343 Entity entity;
1344 auto contents = std::make_unique<SolidColorContents>();
1345 contents->SetGeometry(std::move(geometry));
1346 contents->SetColor(Color::Black());
1347 entity.SetContents(std::move(contents));
1348 auto actual = entity.GetCoverage();
1349 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1350 ASSERT_TRUE(actual.has_value());
1351 ASSERT_RECT_NEAR(actual.value(), expected);
1352 }
1353
1354 // Cover the Cap::kSquare case.
1355 {
1356 auto geometry = Geometry::MakeStrokePath(
1357 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1358 Cap::kSquare, Join::kBevel);
1359
1360 Entity entity;
1361 auto contents = std::make_unique<SolidColorContents>();
1362 contents->SetGeometry(std::move(geometry));
1363 contents->SetColor(Color::Black());
1364 entity.SetContents(std::move(contents));
1365 auto actual = entity.GetCoverage();
1366 auto expected =
1367 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1368 ASSERT_TRUE(actual.has_value());
1369 ASSERT_RECT_NEAR(actual.value(), expected);
1370 }
1371
1372 // Cover the Join::kMiter case.
1373 {
1374 auto geometry = Geometry::MakeStrokePath(
1375 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1376 Cap::kSquare, Join::kMiter);
1377
1378 Entity entity;
1379 auto contents = std::make_unique<SolidColorContents>();
1380 contents->SetGeometry(std::move(geometry));
1381 contents->SetColor(Color::Black());
1382 entity.SetContents(std::move(contents));
1383 auto actual = entity.GetCoverage();
1384 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1385 ASSERT_TRUE(actual.has_value());
1386 ASSERT_RECT_NEAR(actual.value(), expected);
1387 }
1388}

◆ TEST_P() [357/435]

impeller::testing::TEST_P ( EntityTest  ,
SpecializationConstantsAreAppliedToVariants   
)

Definition at line 2621 of file entity_unittests.cc.

2621 {
2622 auto content_context = GetContentContext();
2623
2624 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2625 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2626 .has_depth_stencil_attachments = false,
2627 });
2628 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2629 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2630 .has_depth_stencil_attachments = true});
2631
2632 EXPECT_NE(default_gyph, alt_gyph);
2633 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2634 alt_gyph->GetDescriptor().GetSpecializationConstants());
2635
2636 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2637 PixelFormat::kA8UNormInt;
2638
2639 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2640 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2641 expected_constants);
2642}

◆ TEST_P() [358/435]

impeller::testing::TEST_P ( EntityTest  ,
SrgbToLinearFilter   
)

Definition at line 1999 of file entity_unittests.cc.

1999 {
2000 auto image = CreateTextureForFixture("embarcadero.jpg");
2001 ASSERT_TRUE(image);
2002
2003 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2004 auto filtered =
2005 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
2006
2007 // Define the entity that will serve as the control image as a Gaussian blur
2008 // filter with no filter at all.
2009 Entity entity_left;
2010 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
2011 Matrix::MakeTranslation({100, 300}) *
2012 Matrix::MakeScale(Vector2{0.5, 0.5}));
2013 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
2014 Sigma{0}, Sigma{0});
2015 entity_left.SetContents(unfiltered);
2016
2017 // Define the entity that will be filtered from sRGB to linear.
2018 Entity entity_right;
2019 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
2020 Matrix::MakeTranslation({500, 300}) *
2021 Matrix::MakeScale(Vector2{0.5, 0.5}));
2022 entity_right.SetContents(filtered);
2023 return entity_left.Render(context, pass) &&
2024 entity_right.Render(context, pass);
2025 };
2026
2027 ASSERT_TRUE(OpenPlaygroundHere(callback));
2028}

◆ TEST_P() [359/435]

impeller::testing::TEST_P ( EntityTest  ,
SrgbToLinearFilterCoverageIsCorrect   
)

Definition at line 1978 of file entity_unittests.cc.

1978 {
1979 // Set up a simple color background.
1980 auto fill = std::make_shared<SolidColorContents>();
1981 fill->SetGeometry(Geometry::MakeFillPath(
1982 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1983 fill->SetColor(Color::DeepPink());
1984
1985 auto filter =
1986 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1987
1988 Entity e;
1989 e.SetTransform(Matrix());
1990
1991 // Confirm that the actual filter coverage matches the expected coverage.
1992 auto actual = filter->GetCoverage(e);
1993 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1994
1995 ASSERT_TRUE(actual.has_value());
1996 ASSERT_RECT_NEAR(actual.value(), expected);
1997}

◆ TEST_P() [360/435]

impeller::testing::TEST_P ( EntityTest  ,
StrokeCapAndJoinTest   
)

Definition at line 383 of file entity_unittests.cc.

383 {
384 const Point padding(300, 250);
385 const Point margin(140, 180);
386
387 auto callback = [&](ContentContext& context, RenderPass& pass) {
388 // Slightly above sqrt(2) by default, so that right angles are just below
389 // the limit and acute angles are over the limit (causing them to get
390 // beveled).
391 static Scalar miter_limit = 1.41421357;
392 static Scalar width = 30;
393
394 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
395 {
396 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
397 ImGui::SliderFloat("Stroke width", &width, 0, 100);
398 if (ImGui::Button("Reset")) {
399 miter_limit = 1.41421357;
400 width = 30;
401 }
402 }
403 ImGui::End();
404
405 auto world_matrix = Matrix::MakeScale(GetContentScale());
406 auto render_path = [width = width, &context, &pass, &world_matrix](
407 const Path& path, Cap cap, Join join) {
408 auto contents = std::make_unique<SolidColorContents>();
409 contents->SetGeometry(
410 Geometry::MakeStrokePath(path, width, miter_limit, cap, join));
411 contents->SetColor(Color::Red());
412
413 Entity entity;
414 entity.SetTransform(world_matrix);
415 entity.SetContents(std::move(contents));
416
417 auto coverage = entity.GetCoverage();
418 if (coverage.has_value()) {
419 auto bounds_contents = std::make_unique<SolidColorContents>();
420 bounds_contents->SetGeometry(Geometry::MakeFillPath(
421 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
422 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
423 Entity bounds_entity;
424 bounds_entity.SetContents(std::move(bounds_contents));
425 bounds_entity.Render(context, pass);
426 }
427
428 entity.Render(context, pass);
429 };
430
431 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
432 e_def(75, 75);
433 const Scalar r = 30;
434 // Cap::kButt demo.
435 {
436 Point off = Point(0, 0) * padding + margin;
437 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
438 static PlaygroundPoint point_b(off + b_def, r, Color::White());
439 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
440 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
441 static PlaygroundPoint point_d(off + d_def, r, Color::White());
442 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
443 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
444 Cap::kButt, Join::kBevel);
445 }
446
447 // Cap::kSquare demo.
448 {
449 Point off = Point(1, 0) * padding + margin;
450 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
451 static PlaygroundPoint point_b(off + b_def, r, Color::White());
452 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
453 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
454 static PlaygroundPoint point_d(off + d_def, r, Color::White());
455 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
456 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
457 Cap::kSquare, Join::kBevel);
458 }
459
460 // Cap::kRound demo.
461 {
462 Point off = Point(2, 0) * padding + margin;
463 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
464 static PlaygroundPoint point_b(off + b_def, r, Color::White());
465 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
466 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
467 static PlaygroundPoint point_d(off + d_def, r, Color::White());
468 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
469 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
470 Cap::kRound, Join::kBevel);
471 }
472
473 // Join::kBevel demo.
474 {
475 Point off = Point(0, 1) * padding + margin;
476 static PlaygroundPoint point_a =
477 PlaygroundPoint(off + a_def, r, Color::White());
478 static PlaygroundPoint point_b =
479 PlaygroundPoint(off + e_def, r, Color::White());
480 static PlaygroundPoint point_c =
481 PlaygroundPoint(off + c_def, r, Color::White());
482 Point a = DrawPlaygroundPoint(point_a);
483 Point b = DrawPlaygroundPoint(point_b);
484 Point c = DrawPlaygroundPoint(point_c);
485 render_path(
486 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
487 Cap::kButt, Join::kBevel);
488 }
489
490 // Join::kMiter demo.
491 {
492 Point off = Point(1, 1) * padding + margin;
493 static PlaygroundPoint point_a(off + a_def, r, Color::White());
494 static PlaygroundPoint point_b(off + e_def, r, Color::White());
495 static PlaygroundPoint point_c(off + c_def, r, Color::White());
496 Point a = DrawPlaygroundPoint(point_a);
497 Point b = DrawPlaygroundPoint(point_b);
498 Point c = DrawPlaygroundPoint(point_c);
499 render_path(
500 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
501 Cap::kButt, Join::kMiter);
502 }
503
504 // Join::kRound demo.
505 {
506 Point off = Point(2, 1) * padding + margin;
507 static PlaygroundPoint point_a(off + a_def, r, Color::White());
508 static PlaygroundPoint point_b(off + e_def, r, Color::White());
509 static PlaygroundPoint point_c(off + c_def, r, Color::White());
510 Point a = DrawPlaygroundPoint(point_a);
511 Point b = DrawPlaygroundPoint(point_b);
512 Point c = DrawPlaygroundPoint(point_c);
513 render_path(
514 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
515 Cap::kButt, Join::kRound);
516 }
517
518 return true;
519 };
520 ASSERT_TRUE(OpenPlaygroundHere(callback));
521}

◆ TEST_P() [361/435]

impeller::testing::TEST_P ( EntityTest  ,
StrokeWithTextureContents   
)

Definition at line 319 of file entity_unittests.cc.

319 {
320 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
321 Path path = PathBuilder{}
322 .MoveTo({100, 100})
323 .LineTo({100, 200})
324 .MoveTo({100, 300})
325 .LineTo({100, 400})
326 .MoveTo({100, 500})
327 .LineTo({100, 600})
328 .TakePath();
329
330 Entity entity;
331 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
332 auto contents = std::make_unique<TiledTextureContents>();
333 contents->SetGeometry(Geometry::MakeStrokePath(path, 100.0));
334 contents->SetTexture(bridge);
335 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
336 entity.SetContents(std::move(contents));
337 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
338}

◆ TEST_P() [362/435]

impeller::testing::TEST_P ( EntityTest  ,
SweepGradientContentsIsOpaque   
)

Definition at line 2515 of file entity_unittests.cc.

2515 {
2516 RadialGradientContents contents;
2517 contents.SetColors({Color::CornflowerBlue()});
2518 ASSERT_TRUE(contents.IsOpaque());
2519 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2520 ASSERT_FALSE(contents.IsOpaque());
2521 contents.SetColors({Color::CornflowerBlue()});
2522 contents.SetTileMode(Entity::TileMode::kDecal);
2523 ASSERT_FALSE(contents.IsOpaque());
2524}

◆ TEST_P() [363/435]

impeller::testing::TEST_P ( EntityTest  ,
TextContentsCeilsGlyphScaleToDecimal   
)

Definition at line 2564 of file entity_unittests.cc.

2564 {
2565 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f, 12), 0.43f);
2566 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f, 12), 0.53f);
2567 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f, 12), 2.1f);
2568 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
2569}

◆ TEST_P() [364/435]

impeller::testing::TEST_P ( EntityTest  ,
ThreeStrokesInOnePath   
)

Definition at line 300 of file entity_unittests.cc.

300 {
301 Path path = PathBuilder{}
302 .MoveTo({100, 100})
303 .LineTo({100, 200})
304 .MoveTo({100, 300})
305 .LineTo({100, 400})
306 .MoveTo({100, 500})
307 .LineTo({100, 600})
308 .TakePath();
309
310 Entity entity;
311 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
312 auto contents = std::make_unique<SolidColorContents>();
313 contents->SetGeometry(Geometry::MakeStrokePath(path, 5.0));
314 contents->SetColor(Color::Red());
315 entity.SetContents(std::move(contents));
316 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
317}

◆ TEST_P() [365/435]

impeller::testing::TEST_P ( EntityTest  ,
TiledTextureContentsIsOpaque   
)

Definition at line 2526 of file entity_unittests.cc.

2526 {
2527 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2528 TiledTextureContents contents;
2529 contents.SetTexture(bay_bridge);
2530 // This is a placeholder test. Images currently never decompress as opaque
2531 // (whether in Flutter or the playground), and so this should currently always
2532 // return false in practice.
2533 ASSERT_FALSE(contents.IsOpaque());
2534}
bool IsOpaque() const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
void SetTexture(std::shared_ptr< Texture > texture)

◆ TEST_P() [366/435]

impeller::testing::TEST_P ( EntityTest  ,
TiledTextureContentsRendersWithCorrectPipeline   
)

Definition at line 20 of file tiled_texture_contents_unittests.cc.

20 {
21 TextureDescriptor texture_desc;
22 texture_desc.size = {100, 100};
23 texture_desc.type = TextureType::kTexture2D;
24 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
25 texture_desc.storage_mode = StorageMode::kDevicePrivate;
26 auto texture =
27 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
28
29 TiledTextureContents contents;
30 contents.SetTexture(texture);
31 contents.SetGeometry(Geometry::MakeCover());
32
33 auto content_context = GetContentContext();
34 auto buffer = content_context->GetContext()->CreateCommandBuffer();
35 auto render_target =
36 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
37 *content_context->GetContext(), {100, 100},
38 /*mip_count=*/1);
39 auto render_pass = buffer->CreateRenderPass(render_target);
40 auto recording_pass = std::make_shared<RecordingRenderPass>(
41 render_pass, GetContext(), render_target);
42
43 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *recording_pass));
44 const std::vector<Command>& commands = recording_pass->GetCommands();
45
46 ASSERT_EQ(commands.size(), 1u);
47 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
48 "TextureFill Pipeline") != std::string::npos);
49
50 if (GetParam() == PlaygroundBackend::kMetal) {
51 recording_pass->EncodeCommands();
52 }
53}
void SetGeometry(std::shared_ptr< Geometry > geometry)
Set the geometry that this contents will use to render.
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override

◆ TEST_P() [367/435]

impeller::testing::TEST_P ( EntityTest  ,
TiledTextureContentsRendersWithCorrectPipelineExternalOES   
)

Definition at line 57 of file tiled_texture_contents_unittests.cc.

57 {
58 if (GetParam() != PlaygroundBackend::kOpenGLES) {
59 GTEST_SKIP_(
60 "External OES textures are only valid for the OpenGLES backend.");
61 }
62
63 TextureDescriptor texture_desc;
64 texture_desc.size = {100, 100};
65 texture_desc.type = TextureType::kTextureExternalOES;
66 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
67 texture_desc.storage_mode = StorageMode::kDevicePrivate;
68 auto texture =
69 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
70
71 TiledTextureContents contents;
72 contents.SetTexture(texture);
73 contents.SetGeometry(Geometry::MakeCover());
74
75 auto content_context = GetContentContext();
76 auto buffer = content_context->GetContext()->CreateCommandBuffer();
77 auto render_target =
78 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
79 *content_context->GetContext(), {100, 100},
80 /*mip_count=*/1);
81 auto render_pass = buffer->CreateRenderPass(render_target);
82
83 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass));
84 const std::vector<Command>& commands = render_pass->GetCommands();
85
86 ASSERT_EQ(commands.size(), 1u);
87 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
88 "TiledTextureFillExternal Pipeline") != std::string::npos);
89}
dict commands
Definition dom.py:171

◆ TEST_P() [368/435]

impeller::testing::TEST_P ( EntityTest  ,
TriangleInsideASquare   
)

Definition at line 340 of file entity_unittests.cc.

340 {
341 auto callback = [&](ContentContext& context, RenderPass& pass) {
342 Point offset(100, 100);
343
344 static PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
345 Point a = DrawPlaygroundPoint(point_a);
346 static PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
347 Point b = DrawPlaygroundPoint(point_b);
348 static PlaygroundPoint point_c(Point(210, 210) + offset, 20,
349 Color::White());
350 Point c = DrawPlaygroundPoint(point_c);
351 static PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
352 Point d = DrawPlaygroundPoint(point_d);
353 static PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
354 Point e = DrawPlaygroundPoint(point_e);
355 static PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
356 Point f = DrawPlaygroundPoint(point_f);
357 static PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
358 Point g = DrawPlaygroundPoint(point_g);
359 Path path = PathBuilder{}
360 .MoveTo(a)
361 .LineTo(b)
362 .LineTo(c)
363 .LineTo(d)
364 .Close()
365 .MoveTo(e)
366 .LineTo(f)
367 .LineTo(g)
368 .Close()
369 .TakePath();
370
371 Entity entity;
372 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
373 auto contents = std::make_unique<SolidColorContents>();
374 contents->SetGeometry(Geometry::MakeStrokePath(path, 20.0));
375 contents->SetColor(Color::Red());
376 entity.SetContents(std::move(contents));
377
378 return entity.Render(context, pass);
379 };
380 ASSERT_TRUE(OpenPlaygroundHere(callback));
381}
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
PathBuilder & Close()

◆ TEST_P() [369/435]

impeller::testing::TEST_P ( EntityTest  ,
YUVToRGBFilter   
)

Definition at line 2098 of file entity_unittests.cc.

2098 {
2099 if (GetParam() == PlaygroundBackend::kOpenGLES) {
2100 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
2101 GTEST_SKIP_("YUV to RGB filter is not supported on OpenGLES backend yet.");
2102 }
2103
2104 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2105 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
2106 YUVColorSpace::kBT601LimitedRange};
2107 for (int i = 0; i < 2; i++) {
2108 auto yuv_color_space = yuv_color_space_array[i];
2109 auto textures =
2110 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
2111 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
2112 textures[0], textures[1], yuv_color_space);
2113 Entity filter_entity;
2114 filter_entity.SetContents(filter_contents);
2115 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
2116
2117 Entity entity;
2118 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
2119 contents->SetTexture(snapshot->texture);
2120 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
2121 entity.SetContents(contents);
2122 entity.SetTransform(
2123 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
2124 entity.Render(context, pass);
2125 }
2126 return true;
2127 };
2128 ASSERT_TRUE(OpenPlaygroundHere(callback));
2129}
std::vector< std::shared_ptr< FakeTexture > > textures
YUVColorSpace
Definition color.h:55

◆ TEST_P() [370/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
CalculateUVsSimple   
)

Definition at line 325 of file gaussian_blur_filter_contents_unittests.cc.

325 {
326 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
327 auto filter_input = FilterInput::Make(texture);
328 Entity entity;
329 Quad uvs = GaussianBlurFilterContents::CalculateUVs(
330 filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100));
331 std::optional<Rect> uvs_bounds = Rect::MakePointBounds(uvs);
332 EXPECT_TRUE(uvs_bounds.has_value());
333 if (uvs_bounds.has_value()) {
334 EXPECT_TRUE(RectNear(uvs_bounds.value(), Rect::MakeXYWH(0, 0, 1, 1)));
335 }
336}

◆ TEST_P() [371/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
CoverageWithEffectTransform   
)

Definition at line 177 of file gaussian_blur_filter_contents_unittests.cc.

177 {
178 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
179 fml::StatusOr<Scalar> sigma_radius_1 =
180 CalculateSigmaForBlurRadius(1.0, effect_transform);
181 ASSERT_TRUE(sigma_radius_1.ok());
183 /*sigma_x=*/sigma_radius_1.value(),
184 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
185 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
186 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
187 FilterInput::Vector inputs = {FilterInput::Make(texture)};
188 Entity entity;
189 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
190 std::optional<Rect> coverage =
191 contents.GetFilterCoverage(inputs, entity, effect_transform);
192 EXPECT_TRUE(coverage.has_value());
193 if (coverage.has_value()) {
195 Rect::MakeLTRB(100 - 1, 100 - 1, 200 + 1, 200 + 1));
196 }
197}

◆ TEST_P() [372/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
CoverageWithTexture   
)

Definition at line 156 of file gaussian_blur_filter_contents_unittests.cc.

156 {
157 fml::StatusOr<Scalar> sigma_radius_1 =
158 CalculateSigmaForBlurRadius(1.0, Matrix());
159 ASSERT_TRUE(sigma_radius_1.ok());
161 /*sigma_X=*/sigma_radius_1.value(),
162 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
163 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
164 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
165 FilterInput::Vector inputs = {FilterInput::Make(texture)};
166 Entity entity;
167 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
168 std::optional<Rect> coverage =
169 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
170
171 EXPECT_TRUE(coverage.has_value());
172 if (coverage.has_value()) {
173 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
174 }
175}

◆ TEST_P() [373/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
RenderCoverageMatchesGetCoverage   
)

Definition at line 229 of file gaussian_blur_filter_contents_unittests.cc.

229 {
230 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
231 fml::StatusOr<Scalar> sigma_radius_1 =
232 CalculateSigmaForBlurRadius(1.0, Matrix());
233 ASSERT_TRUE(sigma_radius_1.ok());
234 auto contents = std::make_unique<GaussianBlurFilterContents>(
235 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
236 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
237 contents->SetInputs({FilterInput::Make(texture)});
238 std::shared_ptr<ContentContext> renderer = GetContentContext();
239
240 Entity entity;
241 std::optional<Entity> result =
242 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
243 EXPECT_TRUE(result.has_value());
244 if (result.has_value()) {
245 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
246 std::optional<Rect> result_coverage = result.value().GetCoverage();
247 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
248 EXPECT_TRUE(result_coverage.has_value());
249 EXPECT_TRUE(contents_coverage.has_value());
250 if (result_coverage.has_value() && contents_coverage.has_value()) {
251 EXPECT_TRUE(RectNear(contents_coverage.value(),
252 Rect::MakeLTRB(-1, -1, 101, 101)));
254 RectNear(result_coverage.value(), Rect::MakeLTRB(-1, -1, 101, 101)));
255 }
256 }
257}

◆ TEST_P() [374/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
RenderCoverageMatchesGetCoverageRotated   
)

Definition at line 292 of file gaussian_blur_filter_contents_unittests.cc.

293 {
294 std::shared_ptr<Texture> texture = MakeTexture(ISize(400, 300));
295 fml::StatusOr<Scalar> sigma_radius_1 =
296 CalculateSigmaForBlurRadius(1.0, Matrix());
297 auto contents = std::make_unique<GaussianBlurFilterContents>(
298 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
299 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
300 contents->SetInputs({FilterInput::Make(texture)});
301 std::shared_ptr<ContentContext> renderer = GetContentContext();
302
303 Entity entity;
304 // Rotate around the top left corner, then push it over to (100, 100).
305 entity.SetTransform(Matrix::MakeTranslation({400, 100, 0}) *
306 Matrix::MakeRotationZ(Degrees(90.0)));
307 std::optional<Entity> result =
308 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
309 EXPECT_TRUE(result.has_value());
310 if (result.has_value()) {
311 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
312 std::optional<Rect> result_coverage = result.value().GetCoverage();
313 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
314 EXPECT_TRUE(result_coverage.has_value());
315 EXPECT_TRUE(contents_coverage.has_value());
316 if (result_coverage.has_value() && contents_coverage.has_value()) {
317 EXPECT_TRUE(RectNear(contents_coverage.value(),
318 Rect::MakeLTRB(99, 99, 401, 501)));
320 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 99, 401, 501)));
321 }
322 }
323}

◆ TEST_P() [375/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
RenderCoverageMatchesGetCoverageTranslate   
)

Definition at line 259 of file gaussian_blur_filter_contents_unittests.cc.

260 {
261 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
262 fml::StatusOr<Scalar> sigma_radius_1 =
263 CalculateSigmaForBlurRadius(1.0, Matrix());
264 ASSERT_TRUE(sigma_radius_1.ok());
265 auto contents = std::make_unique<GaussianBlurFilterContents>(
266 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
267 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
268 contents->SetInputs({FilterInput::Make(texture)});
269 std::shared_ptr<ContentContext> renderer = GetContentContext();
270
271 Entity entity;
272 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
273 std::optional<Entity> result =
274 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
275
276 EXPECT_TRUE(result.has_value());
277 if (result.has_value()) {
278 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
279 std::optional<Rect> result_coverage = result.value().GetCoverage();
280 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
281 EXPECT_TRUE(result_coverage.has_value());
282 EXPECT_TRUE(contents_coverage.has_value());
283 if (result_coverage.has_value() && contents_coverage.has_value()) {
284 EXPECT_TRUE(RectNear(contents_coverage.value(),
285 Rect::MakeLTRB(99, 199, 201, 301)));
287 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 199, 201, 301)));
288 }
289 }
290}

◆ TEST_P() [376/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
TextureContentsWithDestinationRect   
)

Definition at line 338 of file gaussian_blur_filter_contents_unittests.cc.

338 {
339 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
340 auto texture_contents = std::make_shared<TextureContents>();
341 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
342 texture_contents->SetTexture(texture);
343 texture_contents->SetDestinationRect(Rect::MakeXYWH(
344 50, 40, texture->GetSize().width, texture->GetSize().height));
345
346 fml::StatusOr<Scalar> sigma_radius_1 =
347 CalculateSigmaForBlurRadius(1.0, Matrix());
348 auto contents = std::make_unique<GaussianBlurFilterContents>(
349 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
350 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
351 contents->SetInputs({FilterInput::Make(texture_contents)});
352 std::shared_ptr<ContentContext> renderer = GetContentContext();
353
354 Entity entity;
355 std::optional<Entity> result =
356 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
357 EXPECT_TRUE(result.has_value());
358 if (result.has_value()) {
359 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
360 std::optional<Rect> result_coverage = result.value().GetCoverage();
361 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
362 EXPECT_TRUE(result_coverage.has_value());
363 EXPECT_TRUE(contents_coverage.has_value());
364 if (result_coverage.has_value() && contents_coverage.has_value()) {
365 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
366 EXPECT_TRUE(RectNear(result_coverage.value(),
367 Rect::MakeLTRB(49.f, 39.f, 151.f, 141.f)));
368 }
369 }
370}

◆ TEST_P() [377/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
TextureContentsWithDestinationRectScaled   
)

Definition at line 372 of file gaussian_blur_filter_contents_unittests.cc.

373 {
374 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
375 auto texture_contents = std::make_shared<TextureContents>();
376 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
377 texture_contents->SetTexture(texture);
378 texture_contents->SetDestinationRect(Rect::MakeXYWH(
379 50, 40, texture->GetSize().width, texture->GetSize().height));
380
381 fml::StatusOr<Scalar> sigma_radius_1 =
382 CalculateSigmaForBlurRadius(1.0, Matrix());
383 auto contents = std::make_unique<GaussianBlurFilterContents>(
384 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
385 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
386 contents->SetInputs({FilterInput::Make(texture_contents)});
387 std::shared_ptr<ContentContext> renderer = GetContentContext();
388
389 Entity entity;
390 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
391 std::optional<Entity> result =
392 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
393 EXPECT_TRUE(result.has_value());
394 if (result.has_value()) {
395 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
396 std::optional<Rect> result_coverage = result.value().GetCoverage();
397 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
398 EXPECT_TRUE(result_coverage.has_value());
399 EXPECT_TRUE(contents_coverage.has_value());
400 if (result_coverage.has_value() && contents_coverage.has_value()) {
401 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
402 EXPECT_TRUE(RectNear(contents_coverage.value(),
403 Rect::MakeLTRB(98.f, 78.f, 302.f, 282.f)));
404 }
405 }
406}

◆ TEST_P() [378/435]

impeller::testing::TEST_P ( GaussianBlurFilterContentsTest  ,
TextureContentsWithEffectTransform   
)

Definition at line 408 of file gaussian_blur_filter_contents_unittests.cc.

408 {
409 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
410 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
411 auto texture_contents = std::make_shared<TextureContents>();
412 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
413 texture_contents->SetTexture(texture);
414 texture_contents->SetDestinationRect(Rect::MakeXYWH(
415 50, 40, texture->GetSize().width, texture->GetSize().height));
416
417 fml::StatusOr<Scalar> sigma_radius_1 =
418 CalculateSigmaForBlurRadius(1.0, effect_transform);
419 ASSERT_TRUE(sigma_radius_1.ok());
420 auto contents = std::make_unique<GaussianBlurFilterContents>(
421 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
422 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
423 contents->SetInputs({FilterInput::Make(texture_contents)});
424 contents->SetEffectTransform(effect_transform);
425 std::shared_ptr<ContentContext> renderer = GetContentContext();
426
427 Entity entity;
428 std::optional<Entity> result =
429 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
430 EXPECT_TRUE(result.has_value());
431 if (result.has_value()) {
432 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
433 std::optional<Rect> result_coverage = result.value().GetCoverage();
434 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
435 EXPECT_TRUE(result_coverage.has_value());
436 EXPECT_TRUE(contents_coverage.has_value());
437 if (result_coverage.has_value() && contents_coverage.has_value()) {
438 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
439 EXPECT_TRUE(RectNear(contents_coverage.value(),
440 Rect::MakeXYWH(49.f, 39.f, 102.f, 102.f)));
441 }
442 }
443}

◆ TEST_P() [379/435]

impeller::testing::TEST_P ( HostBufferTest  ,
CanEmplace   
)

Definition at line 15 of file host_buffer_unittests.cc.

15 {
16 struct Length2 {
17 uint8_t pad[2];
18 };
19 static_assert(sizeof(Length2) == 2u);
20
21 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
22
23 for (size_t i = 0; i < 12500; i++) {
24 auto view = buffer->Emplace(Length2{});
25 ASSERT_TRUE(view);
26 ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u));
27 }
28}

◆ TEST_P() [380/435]

impeller::testing::TEST_P ( HostBufferTest  ,
CanEmplaceWithAlignment   
)

Definition at line 30 of file host_buffer_unittests.cc.

30 {
31 struct Length2 {
32 uint8_t pad[2];
33 };
34 static_assert(sizeof(Length2) == 2);
35 struct alignas(16) Align16 {
36 uint8_t pad[2];
37 };
38 static_assert(alignof(Align16) == 16);
39 static_assert(sizeof(Align16) == 16);
40
41 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
42 ASSERT_TRUE(buffer);
43
44 {
45 auto view = buffer->Emplace(Length2{});
46 ASSERT_TRUE(view);
47 ASSERT_EQ(view.range, Range(0u, 2u));
48 }
49
50 {
51 auto view = buffer->Emplace(Align16{});
52 ASSERT_TRUE(view);
53 ASSERT_EQ(view.range.offset, 16u);
54 ASSERT_EQ(view.range.length, 16u);
55 }
56 {
57 auto view = buffer->Emplace(Length2{});
58 ASSERT_TRUE(view);
59 ASSERT_EQ(view.range, Range(32u, 2u));
60 }
61
62 {
63 auto view = buffer->Emplace(Align16{});
64 ASSERT_TRUE(view);
65 ASSERT_EQ(view.range.offset, 48u);
66 ASSERT_EQ(view.range.length, 16u);
67 }
68}

◆ TEST_P() [381/435]

impeller::testing::TEST_P ( HostBufferTest  ,
EmplaceWithProcIsAligned   
)

Definition at line 149 of file host_buffer_unittests.cc.

149 {
150 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
151
152 BufferView view = buffer->Emplace(std::array<char, 21>());
153 EXPECT_EQ(view.range, Range(0, 21));
154
155 view = buffer->Emplace(64, 16, [](uint8_t*) {});
156 EXPECT_EQ(view.range, Range(32, 64));
157}

◆ TEST_P() [382/435]

impeller::testing::TEST_P ( HostBufferTest  ,
EmplacingLargerThanBlockSizeCreatesOneOffBuffer   
)

Definition at line 106 of file host_buffer_unittests.cc.

106 {
107 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
108
109 // Emplace an amount larger than the block size, to verify that the host
110 // buffer does not create a buffer.
111 auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0);
112
113 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
114 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
115 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
116}

◆ TEST_P() [383/435]

impeller::testing::TEST_P ( HostBufferTest  ,
EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback   
)

Definition at line 93 of file host_buffer_unittests.cc.

94 {
95 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
96
97 // Emplace an amount larger than the block size, to verify that the host
98 // buffer does not create a buffer.
99 auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {});
100
101 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
102 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
103 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
104}

◆ TEST_P() [384/435]

impeller::testing::TEST_P ( HostBufferTest  ,
HostBufferInitialState   
)

Definition at line 70 of file host_buffer_unittests.cc.

70 {
71 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
72
73 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
74 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
75 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
76}

◆ TEST_P() [385/435]

impeller::testing::TEST_P ( HostBufferTest  ,
ResetIncrementsFrameCounter   
)

Definition at line 78 of file host_buffer_unittests.cc.

78 {
79 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
80
81 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
82
83 buffer->Reset();
84 EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u);
85
86 buffer->Reset();
87 EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u);
88
89 buffer->Reset();
90 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
91}

◆ TEST_P() [386/435]

impeller::testing::TEST_P ( HostBufferTest  ,
UnusedBuffersAreDiscardedWhenResetting   
)

Definition at line 118 of file host_buffer_unittests.cc.

118 {
119 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
120
121 // Emplace two large allocations to force the allocation of a second buffer.
122 auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
123 auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
124
125 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u);
126 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
127 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
128
129 // Reset until we get back to this frame.
130 for (auto i = 0; i < 3; i++) {
131 buffer->Reset();
132 }
133
134 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
135 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
136 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
137
138 // Now when we reset, the buffer should get dropped.
139 // Reset until we get back to this frame.
140 for (auto i = 0; i < 3; i++) {
141 buffer->Reset();
142 }
143
144 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
145 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
146 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
147}

◆ TEST_P() [387/435]

impeller::testing::TEST_P ( RendererDartTest  ,
CanCreateRenderPassAndSubmit   
)

Definition at line 302 of file renderer_dart_unittests.cc.

302 {
303 ASSERT_TRUE(RenderDartToPlayground("canCreateRenderPassAndSubmit"));
304}

◆ TEST_P() [388/435]

impeller::testing::TEST_P ( RendererDartTest  ,
CanCreateShaderLibrary   
)

Definition at line 290 of file renderer_dart_unittests.cc.

290 {
291 ASSERT_TRUE(RunDartFunction("canCreateShaderLibrary"));
292}

◆ TEST_P() [389/435]

impeller::testing::TEST_P ( RendererDartTest  ,
CanInstantiateFlutterGPUContext   
)

These test entries correspond to Dart functions located in flutter/impeller/fixtures/dart_tests.dart

Definition at line 286 of file renderer_dart_unittests.cc.

286 {
287 ASSERT_TRUE(RunDartFunction("instantiateDefaultContext"));
288}

◆ TEST_P() [390/435]

impeller::testing::TEST_P ( RendererDartTest  ,
CanReflectUniformStructs   
)

Definition at line 294 of file renderer_dart_unittests.cc.

294 {
295 ASSERT_TRUE(RunDartFunction("canReflectUniformStructs"));
296}

◆ TEST_P() [391/435]

impeller::testing::TEST_P ( RendererDartTest  ,
CanRunDartInPlaygroundFrame   
)

Definition at line 271 of file renderer_dart_unittests.cc.

271 {
272 SinglePassCallback callback = [&](RenderPass& pass) {
273 ImGui::Begin("Dart test", nullptr);
274 ImGui::Text(
275 "This test executes Dart code during the playground frame callback.");
276 ImGui::End();
277
278 return RunDartFunction("sayHi");
279 };
280 ASSERT_TRUE(OpenPlaygroundHere(callback));
281}

◆ TEST_P() [392/435]

impeller::testing::TEST_P ( RendererDartTest  ,
UniformBindFailsForInvalidHostBufferOffset   
)

Definition at line 298 of file renderer_dart_unittests.cc.

298 {
299 ASSERT_TRUE(RunDartFunction("uniformBindFailsForInvalidHostBufferOffset"));
300}

◆ TEST_P() [393/435]

impeller::testing::TEST_P ( RendererTest  ,
ArrayUniforms   
)

Definition at line 884 of file renderer_unittests.cc.

884 {
885 using VS = ArrayVertexShader;
886 using FS = ArrayFragmentShader;
887
888 auto context = GetContext();
889 auto pipeline_descriptor =
891 ASSERT_TRUE(pipeline_descriptor.has_value());
892 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
893 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
894 auto pipeline =
895 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
896 ASSERT_TRUE(pipeline && pipeline->IsValid());
897
898 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
899 SinglePassCallback callback = [&](RenderPass& pass) {
900 auto size = pass.GetRenderTargetSize();
901
902 pass.SetPipeline(pipeline);
903 pass.SetCommandLabel("Google Dots");
905 builder.AddVertices({{Point()},
906 {Point(0, size.height)},
907 {Point(size.width, 0)},
908 {Point(size.width, 0)},
909 {Point(0, size.height)},
910 {Point(size.width, size.height)}});
911 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
912
913 VS::FrameInfo frame_info;
914 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
915 frame_info.mvp =
916 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
917 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
918
919 auto time = GetSecondsElapsed();
920 auto y_pos = [&time](float x) {
921 return 400 + 10 * std::cos(time * 5 + x / 6);
922 };
923
924 FS::FragInfo fs_uniform = {
925 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
926 Point(530, y_pos(2)), Point(580, y_pos(3))},
927 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
928 Color::MakeRGBA8(219, 68, 55, 255),
929 Color::MakeRGBA8(244, 180, 0, 255),
930 Color::MakeRGBA8(15, 157, 88, 255)},
931 };
932 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
933
934 pass.Draw();
935 host_buffer->Reset();
936 return true;
937 };
938 OpenPlaygroundHere(callback);
939}

◆ TEST_P() [394/435]

impeller::testing::TEST_P ( RendererTest  ,
CachesRenderPassAndFramebuffer   
)

Definition at line 16 of file render_pass_cache_unittests.cc.

16 {
17 if (GetBackend() != PlaygroundBackend::kVulkan) {
18 GTEST_SKIP() << "Test only applies to Vulkan";
19 }
20
21 auto allocator = std::make_shared<RenderTargetAllocator>(
22 GetContext()->GetResourceAllocator());
23
24 auto render_target =
25 allocator->CreateOffscreenMSAA(*GetContext(), {100, 100}, 1);
26 auto resolve_texture =
27 render_target.GetColorAttachments().find(0u)->second.resolve_texture;
28 auto& texture_vk = TextureVK::Cast(*resolve_texture);
29
30 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), nullptr);
31 EXPECT_EQ(texture_vk.GetCachedRenderPass(), nullptr);
32
33 auto buffer = GetContext()->CreateCommandBuffer();
34 auto render_pass = buffer->CreateRenderPass(render_target);
35
36 EXPECT_NE(texture_vk.GetCachedFramebuffer(), nullptr);
37 EXPECT_NE(texture_vk.GetCachedRenderPass(), nullptr);
38
39 render_pass->EncodeCommands();
40 GetContext()->GetCommandQueue()->Submit({buffer});
41
42 // Can be reused without error.
43 auto buffer_2 = GetContext()->CreateCommandBuffer();
44 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
45
46 EXPECT_TRUE(render_pass_2->EncodeCommands());
47 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
48}

◆ TEST_P() [395/435]

impeller::testing::TEST_P ( RendererTest  ,
CanBlitTextureToBuffer   
)

Definition at line 567 of file renderer_unittests.cc.

567 {
568 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
569 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
570 }
571 auto context = GetContext();
572 ASSERT_TRUE(context);
573
574 using VS = MipmapsVertexShader;
575 using FS = MipmapsFragmentShader;
577 ASSERT_TRUE(desc.has_value());
578 desc->SetSampleCount(SampleCount::kCount4);
579 desc->SetStencilAttachmentDescriptors(std::nullopt);
580 auto mipmaps_pipeline =
581 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
582 ASSERT_TRUE(mipmaps_pipeline);
583
584 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
585 auto boston = CreateTextureForFixture("boston.jpg");
586 ASSERT_TRUE(bridge && boston);
587 const std::unique_ptr<const Sampler>& sampler =
588 context->GetSamplerLibrary()->GetSampler({});
589 ASSERT_TRUE(sampler);
590
591 TextureDescriptor texture_desc;
592 texture_desc.storage_mode = StorageMode::kHostVisible;
593 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
594 texture_desc.size = bridge->GetTextureDescriptor().size;
595 texture_desc.mip_count = 1u;
596 texture_desc.usage = TextureUsage::kRenderTarget |
597 TextureUsage::kShaderWrite | TextureUsage::kShaderRead;
598 DeviceBufferDescriptor device_buffer_desc;
599 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
600 device_buffer_desc.size =
601 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
602 auto device_buffer =
603 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
604
605 // Vertex buffer.
606 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
607 vertex_builder.SetLabel("Box");
608 auto size = Point(boston->GetSize());
609 vertex_builder.AddVertices({
610 {{0, 0}, {0.0, 0.0}}, // 1
611 {{size.x, 0}, {1.0, 0.0}}, // 2
612 {{size.x, size.y}, {1.0, 1.0}}, // 3
613 {{0, 0}, {0.0, 0.0}}, // 1
614 {{size.x, size.y}, {1.0, 1.0}}, // 3
615 {{0, size.y}, {0.0, 1.0}}, // 4
616 });
617 auto vertex_buffer =
618 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
619 ASSERT_TRUE(vertex_buffer);
620
621 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
622 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
623 {
624 auto buffer = context->CreateCommandBuffer();
625 if (!buffer) {
626 return false;
627 }
628 buffer->SetLabel("Playground Command Buffer");
629 auto pass = buffer->CreateBlitPass();
630 if (!pass) {
631 return false;
632 }
633 pass->SetLabel("Playground Blit Pass");
634
635 if (render_target.GetColorAttachments().empty()) {
636 return false;
637 }
638
639 // Blit `bridge` to the top left corner of the texture.
640 pass->AddCopy(bridge, device_buffer);
641 pass->EncodeCommands(context->GetResourceAllocator());
642
643 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
644 return false;
645 }
646 }
647
648 {
649 auto buffer = context->CreateCommandBuffer();
650 if (!buffer) {
651 return false;
652 }
653 buffer->SetLabel("Playground Command Buffer");
654
655 auto pass = buffer->CreateRenderPass(render_target);
656 if (!pass) {
657 return false;
658 }
659 pass->SetLabel("Playground Render Pass");
660 {
661 pass->SetCommandLabel("Image");
662 pass->SetPipeline(mipmaps_pipeline);
663 pass->SetVertexBuffer(vertex_buffer);
664
665 VS::FrameInfo frame_info;
666 EXPECT_EQ(pass->GetOrthographicTransform(),
667 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
668 frame_info.mvp = pass->GetOrthographicTransform() *
669 Matrix::MakeScale(GetContentScale());
670 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
671
672 FS::FragInfo frag_info;
673 frag_info.lod = 0;
674 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
675
676 const std::unique_ptr<const Sampler>& sampler =
677 context->GetSamplerLibrary()->GetSampler({});
678 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
679 auto texture =
680 context->GetResourceAllocator()->CreateTexture(texture_desc);
681 if (!texture->SetContents(device_buffer->OnGetContents(),
682 buffer_view.range.length)) {
683 VALIDATION_LOG << "Could not upload texture to device memory";
684 return false;
685 }
686 FS::BindTex(*pass, texture, sampler);
687
688 pass->Draw().ok();
689 }
690 pass->EncodeCommands();
691 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
692 return false;
693 }
694 }
695 host_buffer->Reset();
696 return true;
697 };
698 OpenPlaygroundHere(callback);
699}
#define VALIDATION_LOG
Definition validation.h:73

◆ TEST_P() [396/435]

impeller::testing::TEST_P ( RendererTest  ,
CanBlitTextureToTexture   
)

Definition at line 452 of file renderer_unittests.cc.

452 {
453 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
454 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
455 }
456 auto context = GetContext();
457 ASSERT_TRUE(context);
458
459 using VS = MipmapsVertexShader;
460 using FS = MipmapsFragmentShader;
462 ASSERT_TRUE(desc.has_value());
463 desc->SetSampleCount(SampleCount::kCount4);
464 desc->SetStencilAttachmentDescriptors(std::nullopt);
465 auto mipmaps_pipeline =
466 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
467 ASSERT_TRUE(mipmaps_pipeline);
468
469 TextureDescriptor texture_desc;
470 texture_desc.storage_mode = StorageMode::kHostVisible;
471 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
472 texture_desc.size = {800, 600};
473 texture_desc.mip_count = 1u;
474 texture_desc.usage = TextureUsage::kRenderTarget | TextureUsage::kShaderRead;
475 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
476 ASSERT_TRUE(texture);
477
478 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
479 auto boston = CreateTextureForFixture("boston.jpg");
480 ASSERT_TRUE(bridge && boston);
481 const std::unique_ptr<const Sampler>& sampler =
482 context->GetSamplerLibrary()->GetSampler({});
483 ASSERT_TRUE(sampler);
484
485 // Vertex buffer.
486 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
487 vertex_builder.SetLabel("Box");
488 auto size = Point(boston->GetSize());
489 vertex_builder.AddVertices({
490 {{0, 0}, {0.0, 0.0}}, // 1
491 {{size.x, 0}, {1.0, 0.0}}, // 2
492 {{size.x, size.y}, {1.0, 1.0}}, // 3
493 {{0, 0}, {0.0, 0.0}}, // 1
494 {{size.x, size.y}, {1.0, 1.0}}, // 3
495 {{0, size.y}, {0.0, 1.0}}, // 4
496 });
497 auto vertex_buffer =
498 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
499 ASSERT_TRUE(vertex_buffer);
500
501 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
502 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
503 auto buffer = context->CreateCommandBuffer();
504 if (!buffer) {
505 return false;
506 }
507 buffer->SetLabel("Playground Command Buffer");
508
509 {
510 auto pass = buffer->CreateBlitPass();
511 if (!pass) {
512 return false;
513 }
514 pass->SetLabel("Playground Blit Pass");
515
516 if (render_target.GetColorAttachments().empty()) {
517 return false;
518 }
519
520 // Blit `bridge` to the top left corner of the texture.
521 pass->AddCopy(bridge, texture);
522
523 if (!pass->EncodeCommands(context->GetResourceAllocator())) {
524 return false;
525 }
526 }
527
528 {
529 auto pass = buffer->CreateRenderPass(render_target);
530 if (!pass) {
531 return false;
532 }
533 pass->SetLabel("Playground Render Pass");
534 {
535 pass->SetCommandLabel("Image");
536 pass->SetPipeline(mipmaps_pipeline);
537 pass->SetVertexBuffer(vertex_buffer);
538
539 VS::FrameInfo frame_info;
540 EXPECT_EQ(pass->GetOrthographicTransform(),
541 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
542 frame_info.mvp = pass->GetOrthographicTransform() *
543 Matrix::MakeScale(GetContentScale());
544 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
545
546 FS::FragInfo frag_info;
547 frag_info.lod = 0;
548 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
549
550 auto& sampler = context->GetSamplerLibrary()->GetSampler({});
551 FS::BindTex(*pass, texture, sampler);
552
553 pass->Draw();
554 }
555 pass->EncodeCommands();
556 }
557
558 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
559 return false;
560 }
561 host_buffer->Reset();
562 return true;
563 };
564 OpenPlaygroundHere(callback);
565}

◆ TEST_P() [397/435]

impeller::testing::TEST_P ( RendererTest  ,
CanCreateBoxPrimitive   
)

Definition at line 50 of file renderer_unittests.cc.

50 {
51 using VS = BoxFadeVertexShader;
52 using FS = BoxFadeFragmentShader;
53 auto context = GetContext();
54 ASSERT_TRUE(context);
55 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
56 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
57 ASSERT_TRUE(desc.has_value());
58 desc->SetSampleCount(SampleCount::kCount4);
59 desc->SetStencilAttachmentDescriptors(std::nullopt);
60
61 // Vertex buffer.
63 vertex_builder.SetLabel("Box");
64 vertex_builder.AddVertices({
65 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
66 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
67 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
68 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
69 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
70 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
71 });
72 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
73 auto boston = CreateTextureForFixture("boston.jpg");
74 ASSERT_TRUE(bridge && boston);
75 const std::unique_ptr<const Sampler>& sampler =
76 context->GetSamplerLibrary()->GetSampler({});
77 ASSERT_TRUE(sampler);
78
79 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
80 SinglePassCallback callback = [&](RenderPass& pass) {
81 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
82 static bool wireframe;
83 ImGui::Checkbox("Wireframe", &wireframe);
84 ImGui::End();
85
86 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
87 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
88
89 assert(pipeline && pipeline->IsValid());
90
91 pass.SetCommandLabel("Box");
92 pass.SetPipeline(pipeline);
93 pass.SetVertexBuffer(
94 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
95
96 VS::UniformBuffer uniforms;
97 EXPECT_EQ(pass.GetOrthographicTransform(),
98 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
99 uniforms.mvp =
100 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
101 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
102
103 FS::FrameInfo frame_info;
104 frame_info.current_time = GetSecondsElapsed();
105 frame_info.cursor_position = GetCursorPosition();
106 frame_info.window_size.x = GetWindowSize().width;
107 frame_info.window_size.y = GetWindowSize().height;
108
109 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
110 FS::BindContents1(pass, boston, sampler);
111 FS::BindContents2(pass, bridge, sampler);
112
113 host_buffer->Reset();
114 return pass.Draw().ok();
115 };
116 OpenPlaygroundHere(callback);
117}
VertexBuffer CreateVertexBuffer(HostBuffer &host_buffer) const
void SetLabel(const std::string &label)
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)

◆ TEST_P() [398/435]

impeller::testing::TEST_P ( RendererTest  ,
CanCreateCPUBackedTexture   
)

Definition at line 988 of file renderer_unittests.cc.

988 {
989 if (GetParam() == PlaygroundBackend::kOpenGLES) {
990 GTEST_SKIP_("CPU backed textures are not supported on OpenGLES.");
991 }
992
993 auto context = GetContext();
994 auto allocator = context->GetResourceAllocator();
995 size_t dimension = 2;
996
997 do {
998 ISize size(dimension, dimension);
999 TextureDescriptor texture_descriptor;
1000 texture_descriptor.storage_mode = StorageMode::kHostVisible;
1001 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
1002 texture_descriptor.size = size;
1003 auto row_bytes =
1004 std::max(static_cast<uint16_t>(size.width * 4),
1005 allocator->MinimumBytesPerRow(texture_descriptor.format));
1006 auto buffer_size = size.height * row_bytes;
1007
1008 DeviceBufferDescriptor buffer_descriptor;
1009 buffer_descriptor.storage_mode = StorageMode::kHostVisible;
1010 buffer_descriptor.size = buffer_size;
1011
1012 auto buffer = allocator->CreateBuffer(buffer_descriptor);
1013
1014 ASSERT_TRUE(buffer);
1015
1016 auto texture = buffer->AsTexture(*allocator, texture_descriptor, row_bytes);
1017
1018 ASSERT_TRUE(texture);
1019 ASSERT_TRUE(texture->IsValid());
1020
1021 dimension *= 2;
1022 } while (dimension <= 8192);
1023}
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)

◆ TEST_P() [399/435]

impeller::testing::TEST_P ( RendererTest  ,
CanGenerateMipmaps   
)

Definition at line 701 of file renderer_unittests.cc.

701 {
702 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
703 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
704 }
705 auto context = GetContext();
706 ASSERT_TRUE(context);
707
708 using VS = MipmapsVertexShader;
709 using FS = MipmapsFragmentShader;
711 ASSERT_TRUE(desc.has_value());
712 desc->SetSampleCount(SampleCount::kCount4);
713 desc->SetStencilAttachmentDescriptors(std::nullopt);
714 auto mipmaps_pipeline =
715 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
716 ASSERT_TRUE(mipmaps_pipeline);
717
718 auto boston = CreateTextureForFixture("boston.jpg", true);
719 ASSERT_TRUE(boston);
720
721 // Vertex buffer.
723 vertex_builder.SetLabel("Box");
724 auto size = Point(boston->GetSize());
725 vertex_builder.AddVertices({
726 {{0, 0}, {0.0, 0.0}}, // 1
727 {{size.x, 0}, {1.0, 0.0}}, // 2
728 {{size.x, size.y}, {1.0, 1.0}}, // 3
729 {{0, 0}, {0.0, 0.0}}, // 1
730 {{size.x, size.y}, {1.0, 1.0}}, // 3
731 {{0, size.y}, {0.0, 1.0}}, // 4
732 });
733 auto vertex_buffer =
734 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
735 ASSERT_TRUE(vertex_buffer);
736
737 bool first_frame = true;
738 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
739 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
740 const char* mip_filter_names[] = {"Nearest", "Linear"};
741 const MipFilter mip_filters[] = {MipFilter::kNearest, MipFilter::kLinear};
742 const char* min_filter_names[] = {"Nearest", "Linear"};
743 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
744 MinMagFilter::kLinear};
745
746 // UI state.
747 static int selected_mip_filter = 1;
748 static int selected_min_filter = 0;
749 static float lod = 4.5;
750
751 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
752 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
753 sizeof(mip_filter_names) / sizeof(char*));
754 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
755 sizeof(min_filter_names) / sizeof(char*));
756 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
757 ImGui::End();
758
759 auto buffer = context->CreateCommandBuffer();
760 if (!buffer) {
761 return false;
762 }
763 buffer->SetLabel("Playground Command Buffer");
764
765 if (first_frame) {
766 auto pass = buffer->CreateBlitPass();
767 if (!pass) {
768 return false;
769 }
770 pass->SetLabel("Playground Blit Pass");
771
772 pass->GenerateMipmap(boston, "Boston Mipmap");
773
774 pass->EncodeCommands(context->GetResourceAllocator());
775 }
776
777 first_frame = false;
778
779 {
780 auto pass = buffer->CreateRenderPass(render_target);
781 if (!pass) {
782 return false;
783 }
784 pass->SetLabel("Playground Render Pass");
785 {
786 pass->SetCommandLabel("Image LOD");
787 pass->SetPipeline(mipmaps_pipeline);
788 pass->SetVertexBuffer(vertex_buffer);
789
790 VS::FrameInfo frame_info;
791 EXPECT_EQ(pass->GetOrthographicTransform(),
792 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
793 frame_info.mvp = pass->GetOrthographicTransform() *
794 Matrix::MakeScale(GetContentScale());
795 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
796
797 FS::FragInfo frag_info;
798 frag_info.lod = lod;
799 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
800
801 SamplerDescriptor sampler_desc;
802 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
803 sampler_desc.min_filter = min_filters[selected_min_filter];
804 const std::unique_ptr<const Sampler>& sampler =
805 context->GetSamplerLibrary()->GetSampler(sampler_desc);
806 FS::BindTex(*pass, boston, sampler);
807
808 pass->Draw();
809 }
810 pass->EncodeCommands();
811 }
812
813 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
814 return false;
815 }
816 host_buffer->Reset();
817 return true;
818 };
819 OpenPlaygroundHere(callback);
820}

◆ TEST_P() [400/435]

impeller::testing::TEST_P ( RendererTest  ,
CanLookupRenderTargetProperties   
)

Definition at line 1265 of file renderer_unittests.cc.

1265 {
1266 auto context = GetContext();
1267 auto cmd_buffer = context->CreateCommandBuffer();
1268 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1269 GetContext()->GetResourceAllocator());
1270
1271 auto render_target = render_target_cache->CreateOffscreen(
1272 *context, {100, 100}, /*mip_count=*/1);
1273 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1274
1275 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1276 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1277 render_target.GetRenderTargetPixelFormat());
1278 EXPECT_EQ(render_pass->HasStencilAttachment(),
1279 render_target.GetStencilAttachment().has_value());
1280 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1281 render_target.GetRenderTargetSize());
1282 render_pass->EncodeCommands();
1283}

◆ TEST_P() [401/435]

impeller::testing::TEST_P ( RendererTest  ,
CanRenderInstanced   
)

Definition at line 384 of file renderer_unittests.cc.

384 {
385 if (GetParam() == PlaygroundBackend::kOpenGLES) {
386 GTEST_SKIP_("Instancing is not supported on OpenGL.");
387 }
388 using VS = InstancedDrawVertexShader;
389 using FS = InstancedDrawFragmentShader;
390
392
393 ASSERT_EQ(Tessellator::Result::kSuccess,
395 PathBuilder{}
396 .AddRect(Rect::MakeXYWH(10, 10, 100, 100))
397 .TakePath(FillType::kOdd),
398 1.0f,
399 [&builder](const float* vertices, size_t vertices_count,
400 const uint16_t* indices, size_t indices_count) {
401 for (auto i = 0u; i < vertices_count * 2; i += 2) {
402 VS::PerVertexData data;
403 data.vtx = {vertices[i], vertices[i + 1]};
404 builder.AppendVertex(data);
405 }
406 for (auto i = 0u; i < indices_count; i++) {
407 builder.AppendIndex(indices[i]);
408 }
409 return true;
410 }));
411
412 ASSERT_NE(GetContext(), nullptr);
413 auto pipeline =
414 GetContext()
415 ->GetPipelineLibrary()
416 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
417 *GetContext())
418 ->SetSampleCount(SampleCount::kCount4)
419 .SetStencilAttachmentDescriptors(std::nullopt))
420
421 .Get();
422 ASSERT_TRUE(pipeline && pipeline->IsValid());
423
424 static constexpr size_t kInstancesCount = 5u;
425 VS::InstanceInfo<kInstancesCount> instances;
426 for (size_t i = 0; i < kInstancesCount; i++) {
427 instances.colors[i] = Color::Random();
428 }
429
430 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
431 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
432 pass.SetPipeline(pipeline);
433 pass.SetCommandLabel("InstancedDraw");
434
435 VS::FrameInfo frame_info;
436 EXPECT_EQ(pass.GetOrthographicTransform(),
437 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
438 frame_info.mvp =
439 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
440 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
441 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
442 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
443
444 pass.SetInstanceCount(kInstancesCount);
445 pass.Draw();
446
447 host_buffer->Reset();
448 return true;
449 }));
450}

◆ TEST_P() [402/435]

impeller::testing::TEST_P ( RendererTest  ,
CanRenderMultiplePrimitives   
)

Definition at line 208 of file renderer_unittests.cc.

208 {
209 using VS = BoxFadeVertexShader;
210 using FS = BoxFadeFragmentShader;
211 auto context = GetContext();
212 ASSERT_TRUE(context);
213 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
214 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
215 ASSERT_TRUE(desc.has_value());
216 desc->SetSampleCount(SampleCount::kCount4);
217 desc->SetStencilAttachmentDescriptors(std::nullopt);
218 auto box_pipeline =
219 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
220 ASSERT_TRUE(box_pipeline);
221
222 // Vertex buffer.
224 vertex_builder.SetLabel("Box");
225 vertex_builder.AddVertices({
226 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
227 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
228 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
229 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
230 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
231 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
232 });
233 auto vertex_buffer =
234 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
235 ASSERT_TRUE(vertex_buffer);
236
237 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
238 auto boston = CreateTextureForFixture("boston.jpg");
239 ASSERT_TRUE(bridge && boston);
240 const std::unique_ptr<const Sampler>& sampler =
241 context->GetSamplerLibrary()->GetSampler({});
242 ASSERT_TRUE(sampler);
243
244 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
245 SinglePassCallback callback = [&](RenderPass& pass) {
246 for (size_t i = 0; i < 1; i++) {
247 for (size_t j = 0; j < 1; j++) {
248 pass.SetCommandLabel("Box");
249 pass.SetPipeline(box_pipeline);
250 pass.SetVertexBuffer(vertex_buffer);
251
252 FS::FrameInfo frame_info;
253 frame_info.current_time = GetSecondsElapsed();
254 frame_info.cursor_position = GetCursorPosition();
255 frame_info.window_size.x = GetWindowSize().width;
256 frame_info.window_size.y = GetWindowSize().height;
257
258 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
259 FS::BindContents1(pass, boston, sampler);
260 FS::BindContents2(pass, bridge, sampler);
261
262 VS::UniformBuffer uniforms;
263 EXPECT_EQ(pass.GetOrthographicTransform(),
264 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
265 uniforms.mvp = pass.GetOrthographicTransform() *
266 Matrix::MakeScale(GetContentScale()) *
267 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
268 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
269 if (!pass.Draw().ok()) {
270 return false;
271 }
272 }
273 }
274
275 host_buffer->Reset();
276 return true;
277 };
278 OpenPlaygroundHere(callback);
279}

◆ TEST_P() [403/435]

impeller::testing::TEST_P ( RendererTest  ,
CanRenderPerspectiveCube   
)

Definition at line 119 of file renderer_unittests.cc.

119 {
120 using VS = ColorsVertexShader;
121 using FS = ColorsFragmentShader;
122 auto context = GetContext();
123 ASSERT_TRUE(context);
125 ASSERT_TRUE(desc.has_value());
126 desc->SetCullMode(CullMode::kBackFace);
127 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
128 desc->SetSampleCount(SampleCount::kCount4);
129 desc->SetStencilAttachmentDescriptors(std::nullopt);
130 auto pipeline =
131 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
132 ASSERT_TRUE(pipeline);
133
134 struct Cube {
135 VS::PerVertexData vertices[8] = {
136 // -Z
137 {{-1, -1, -1}, Color::Red()},
138 {{1, -1, -1}, Color::Yellow()},
139 {{1, 1, -1}, Color::Green()},
140 {{-1, 1, -1}, Color::Blue()},
141 // +Z
142 {{-1, -1, 1}, Color::Green()},
143 {{1, -1, 1}, Color::Blue()},
144 {{1, 1, 1}, Color::Red()},
145 {{-1, 1, 1}, Color::Yellow()},
146 };
147 uint16_t indices[36] = {
148 1, 5, 2, 2, 5, 6, // +X
149 4, 0, 7, 7, 0, 3, // -X
150 4, 5, 0, 0, 5, 1, // +Y
151 3, 2, 7, 7, 2, 6, // -Y
152 5, 4, 6, 6, 4, 7, // +Z
153 0, 1, 3, 3, 1, 2, // -Z
154 };
155 } cube;
156
157 VertexBuffer vertex_buffer;
158 {
159 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
160 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
161 vertex_buffer.vertex_buffer = {
162 .buffer = device_buffer,
163 .range = Range(offsetof(Cube, vertices), sizeof(Cube::vertices))};
164 vertex_buffer.index_buffer = {
165 .buffer = device_buffer,
166 .range = Range(offsetof(Cube, indices), sizeof(Cube::indices))};
167 vertex_buffer.vertex_count = 36;
168 vertex_buffer.index_type = IndexType::k16bit;
169 }
170
171 const std::unique_ptr<const Sampler>& sampler =
172 context->GetSamplerLibrary()->GetSampler({});
173 ASSERT_TRUE(sampler);
174
175 Vector3 euler_angles;
176 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
177 SinglePassCallback callback = [&](RenderPass& pass) {
178 static Degrees fov_y(60);
179 static Scalar distance = 10;
180
181 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
182 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
183 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
184 ImGui::End();
185
186 pass.SetCommandLabel("Perspective Cube");
187 pass.SetPipeline(pipeline);
188 pass.SetVertexBuffer(vertex_buffer);
189
190 VS::UniformBuffer uniforms;
191 Scalar time = GetSecondsElapsed();
192 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
193
194 uniforms.mvp =
195 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
196 Matrix::MakeTranslation({0, 0, distance}) *
197 Matrix::MakeRotationX(Radians(euler_angles.x)) *
198 Matrix::MakeRotationY(Radians(euler_angles.y)) *
199 Matrix::MakeRotationZ(Radians(euler_angles.z));
200 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
201
202 host_buffer->Reset();
203 return pass.Draw().ok();
204 };
205 OpenPlaygroundHere(callback);
206}

◆ TEST_P() [404/435]

impeller::testing::TEST_P ( RendererTest  ,
CanRenderToTexture   
)

Definition at line 281 of file renderer_unittests.cc.

281 {
282 using VS = BoxFadeVertexShader;
283 using FS = BoxFadeFragmentShader;
284 auto context = GetContext();
285 ASSERT_TRUE(context);
286 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
287 auto pipeline_desc =
288 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
289 pipeline_desc->SetSampleCount(SampleCount::kCount1);
290 pipeline_desc->ClearDepthAttachment();
291 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
292
293 ASSERT_TRUE(pipeline_desc.has_value());
294 auto box_pipeline =
295 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
296 ASSERT_TRUE(box_pipeline);
297 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
298
300 vertex_builder.SetLabel("Box");
301 vertex_builder.AddVertices({
302 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
303 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
304 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
305 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
306 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
307 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
308 });
309 auto vertex_buffer =
310 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
311 ASSERT_TRUE(vertex_buffer);
312
313 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
314 auto boston = CreateTextureForFixture("boston.jpg");
315 ASSERT_TRUE(bridge && boston);
316 const std::unique_ptr<const Sampler>& sampler =
317 context->GetSamplerLibrary()->GetSampler({});
318 ASSERT_TRUE(sampler);
319
320 std::shared_ptr<RenderPass> r2t_pass;
321 auto cmd_buffer = context->CreateCommandBuffer();
322 ASSERT_TRUE(cmd_buffer);
323 {
324 ColorAttachment color0;
325 color0.load_action = LoadAction::kClear;
326 color0.store_action = StoreAction::kStore;
327
328 TextureDescriptor texture_descriptor;
329 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
330 texture_descriptor.format =
331 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
332 texture_descriptor.storage_mode = StorageMode::kHostVisible;
333 texture_descriptor.size = {400, 400};
334 texture_descriptor.mip_count = 1u;
335 texture_descriptor.usage = TextureUsage::kRenderTarget;
336
337 color0.texture =
338 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
339
340 ASSERT_TRUE(color0.IsValid());
341
342 color0.texture->SetLabel("r2t_target");
343
344 StencilAttachment stencil0;
345 stencil0.load_action = LoadAction::kClear;
346 stencil0.store_action = StoreAction::kDontCare;
347 TextureDescriptor stencil_texture_desc;
348 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
349 stencil_texture_desc.size = texture_descriptor.size;
350 stencil_texture_desc.format = PixelFormat::kS8UInt;
351 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
352 stencil0.texture =
353 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
354
355 RenderTarget r2t_desc;
356 r2t_desc.SetColorAttachment(color0, 0u);
357 r2t_desc.SetStencilAttachment(stencil0);
358 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
359 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
360 }
361
362 r2t_pass->SetCommandLabel("Box");
363 r2t_pass->SetPipeline(box_pipeline);
364 r2t_pass->SetVertexBuffer(vertex_buffer);
365
366 FS::FrameInfo frame_info;
367 frame_info.current_time = GetSecondsElapsed();
368 frame_info.cursor_position = GetCursorPosition();
369 frame_info.window_size.x = GetWindowSize().width;
370 frame_info.window_size.y = GetWindowSize().height;
371
372 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
373 FS::BindContents1(*r2t_pass, boston, sampler);
374 FS::BindContents2(*r2t_pass, bridge, sampler);
375
376 VS::UniformBuffer uniforms;
377 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
378 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
379 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
380 ASSERT_TRUE(r2t_pass->Draw().ok());
381 ASSERT_TRUE(r2t_pass->EncodeCommands());
382}

◆ TEST_P() [405/435]

impeller::testing::TEST_P ( RendererTest  ,
CanSepiaToneThenSwizzleWithSubpasses   
)

Definition at line 1413 of file renderer_unittests.cc.

1413 {
1414 // The GLES framebuffer fetch implementation currently does not support this.
1415 // TODO(chinmaygarde): revisit after the GLES framebuffer fetch capabilities
1416 // are clarified.
1417 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1418 GTEST_SKIP_("Not supported on GLES.");
1419 }
1420
1421 // Define shader types
1422 using TextureVS = TextureVertexShader;
1423 using TextureFS = TextureFragmentShader;
1424
1425 using SwizzleVS = SepiaVertexShader;
1426 using SwizzleFS = SwizzleFragmentShader;
1427
1428 using SepiaVS = SepiaVertexShader;
1429 using SepiaFS = SepiaFragmentShader;
1430
1431 auto context = GetContext();
1432 ASSERT_TRUE(context);
1433
1434 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1435 GTEST_SKIP_(
1436 "This test uses framebuffer fetch and the backend doesn't support it.");
1437 return;
1438 }
1439
1440 // Create pipelines.
1441 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1442 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1443 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1444
1445 ASSERT_TRUE(texture_pipeline);
1446 ASSERT_TRUE(swizzle_pipeline);
1447 ASSERT_TRUE(sepia_pipeline);
1448
1449 // Vertex buffer builders.
1450 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1451 texture_vtx_builder.AddVertices({
1452 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1453 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1454 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1455 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1456 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1457 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1458 });
1459
1460 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1461 sepia_vtx_builder.AddVertices({
1462 {{100, 100, 0.0}}, // 1
1463 {{800, 100, 0.0}}, // 2
1464 {{800, 800, 0.0}}, // 3
1465 {{100, 100, 0.0}}, // 1
1466 {{800, 800, 0.0}}, // 3
1467 {{100, 800, 0.0}}, // 4
1468 });
1469
1470 auto boston = CreateTextureForFixture("boston.jpg");
1471 ASSERT_TRUE(boston);
1472
1473 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1474 ASSERT_TRUE(sampler);
1475
1476 SinglePassCallback callback = [&](RenderPass& pass) {
1477 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1478
1479 // Draw the texture.
1480 {
1481 pass.SetPipeline(texture_pipeline);
1482 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1483 *context->GetResourceAllocator()));
1484 TextureVS::UniformBuffer uniforms;
1485 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1486 Matrix::MakeScale(GetContentScale());
1487 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1488 TextureFS::BindTextureContents(pass, boston, sampler);
1489 if (!pass.Draw().ok()) {
1490 return false;
1491 }
1492 }
1493
1494 // Draw the sepia toner.
1495 {
1496 pass.SetPipeline(sepia_pipeline);
1497 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1498 *context->GetResourceAllocator()));
1499 SepiaVS::UniformBuffer uniforms;
1500 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1501 Matrix::MakeScale(GetContentScale());
1502 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1503 if (!pass.Draw().ok()) {
1504 return false;
1505 }
1506 }
1507
1508 // Draw the swizzle.
1509 {
1510 pass.SetPipeline(swizzle_pipeline);
1511 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1512 *context->GetResourceAllocator()));
1513 SwizzleVS::UniformBuffer uniforms;
1514 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1515 Matrix::MakeScale(GetContentScale());
1516 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1517 if (!pass.Draw().ok()) {
1518 return false;
1519 }
1520 }
1521
1522 return true;
1523 };
1524 OpenPlaygroundHere(callback);
1525}

◆ TEST_P() [406/435]

impeller::testing::TEST_P ( RendererTest  ,
CanSepiaToneWithSubpasses   
)

Definition at line 1318 of file renderer_unittests.cc.

1318 {
1319 // The GLES framebuffer fetch implementation currently does not support this.
1320 // TODO(chinmaygarde): revisit after the GLES framebuffer fetch capabilities
1321 // are clarified.
1322 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1323 GTEST_SKIP_("Not supported on GLES.");
1324 }
1325
1326 // Define shader types
1327 using TextureVS = TextureVertexShader;
1328 using TextureFS = TextureFragmentShader;
1329
1330 using SepiaVS = SepiaVertexShader;
1331 using SepiaFS = SepiaFragmentShader;
1332
1333 auto context = GetContext();
1334 ASSERT_TRUE(context);
1335
1336 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1337 GTEST_SKIP_(
1338 "This test uses framebuffer fetch and the backend doesn't support it.");
1339 return;
1340 }
1341
1342 // Create pipelines.
1343 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1344 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1345
1346 ASSERT_TRUE(texture_pipeline);
1347 ASSERT_TRUE(sepia_pipeline);
1348
1349 // Vertex buffer builders.
1350 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1351 texture_vtx_builder.AddVertices({
1352 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1353 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1354 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1355 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1356 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1357 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1358 });
1359
1360 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1361 sepia_vtx_builder.AddVertices({
1362 {{100, 100, 0.0}}, // 1
1363 {{800, 100, 0.0}}, // 2
1364 {{800, 800, 0.0}}, // 3
1365 {{100, 100, 0.0}}, // 1
1366 {{800, 800, 0.0}}, // 3
1367 {{100, 800, 0.0}}, // 4
1368 });
1369
1370 auto boston = CreateTextureForFixture("boston.jpg");
1371 ASSERT_TRUE(boston);
1372
1373 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1374 ASSERT_TRUE(sampler);
1375
1376 SinglePassCallback callback = [&](RenderPass& pass) {
1377 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1378
1379 // Draw the texture.
1380 {
1381 pass.SetPipeline(texture_pipeline);
1382 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1383 *context->GetResourceAllocator()));
1384 TextureVS::UniformBuffer uniforms;
1385 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1386 Matrix::MakeScale(GetContentScale());
1387 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1388 TextureFS::BindTextureContents(pass, boston, sampler);
1389 if (!pass.Draw().ok()) {
1390 return false;
1391 }
1392 }
1393
1394 // Draw the sepia toner.
1395 {
1396 pass.SetPipeline(sepia_pipeline);
1397 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1398 *context->GetResourceAllocator()));
1399 SepiaVS::UniformBuffer uniforms;
1400 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1401 Matrix::MakeScale(GetContentScale());
1402 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1403 if (!pass.Draw().ok()) {
1404 return false;
1405 }
1406 }
1407
1408 return true;
1409 };
1410 OpenPlaygroundHere(callback);
1411}

◆ TEST_P() [407/435]

impeller::testing::TEST_P ( RendererTest  ,
DefaultIndexBehavior   
)

Definition at line 1035 of file renderer_unittests.cc.

1035 {
1036 using VS = BoxFadeVertexShader;
1037
1038 // Do not create any index buffer if no indices were provided.
1040 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1041}
constexpr impeller::IndexType GetIndexType() const

◆ TEST_P() [408/435]

impeller::testing::TEST_P ( RendererTest  ,
DefaultIndexSize   
)

Definition at line 1025 of file renderer_unittests.cc.

1025 {
1026 using VS = BoxFadeVertexShader;
1027
1028 // Default to 16bit index buffer size, as this is a reasonable default and
1029 // supported on all backends without extensions.
1031 vertex_builder.AppendIndex(0u);
1032 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1033}
VertexBufferBuilder & AppendIndex(IndexType_ index)

◆ TEST_P() [409/435]

impeller::testing::TEST_P ( RendererTest  ,
InactiveUniforms   
)

Definition at line 941 of file renderer_unittests.cc.

941 {
942 using VS = InactiveUniformsVertexShader;
943 using FS = InactiveUniformsFragmentShader;
944
945 auto context = GetContext();
946 auto pipeline_descriptor =
948 ASSERT_TRUE(pipeline_descriptor.has_value());
949 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
950 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
951 auto pipeline =
952 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
953 ASSERT_TRUE(pipeline && pipeline->IsValid());
954
955 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
956 SinglePassCallback callback = [&](RenderPass& pass) {
957 auto size = pass.GetRenderTargetSize();
958
959 pass.SetPipeline(pipeline);
960 pass.SetCommandLabel("Inactive Uniform");
961
963 builder.AddVertices({{Point()},
964 {Point(0, size.height)},
965 {Point(size.width, 0)},
966 {Point(size.width, 0)},
967 {Point(0, size.height)},
968 {Point(size.width, size.height)}});
969 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
970
971 VS::FrameInfo frame_info;
972 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
973 frame_info.mvp =
974 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
975 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
976
977 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
978 .color = Color::Green()};
979 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
980
981 pass.Draw().ok();
982 host_buffer->Reset();
983 return true;
984 };
985 OpenPlaygroundHere(callback);
986}

◆ TEST_P() [410/435]

impeller::testing::TEST_P ( RendererTest  ,
RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat   
)

Definition at line 1285 of file renderer_unittests.cc.

1286 {
1287 auto context = GetContext();
1288 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1289 GetContext()->GetResourceAllocator());
1290
1291 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1292 *context, {100, 100}, /*mip_count=*/1);
1293 EXPECT_EQ(render_target.GetDepthAttachment()
1294 ->texture->GetTextureDescriptor()
1295 .format,
1296 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1297}

◆ TEST_P() [411/435]

impeller::testing::TEST_P ( RendererTest  ,
StencilMask   
)

Definition at line 1113 of file renderer_unittests.cc.

1113 {
1114 using VS = BoxFadeVertexShader;
1115 using FS = BoxFadeFragmentShader;
1116 auto context = GetContext();
1117 ASSERT_TRUE(context);
1118 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1119 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1120 ASSERT_TRUE(desc.has_value());
1121
1122 // Vertex buffer.
1124 vertex_builder.SetLabel("Box");
1125 vertex_builder.AddVertices({
1126 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1127 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1128 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1129 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1130 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1131 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1132 });
1133 auto vertex_buffer =
1134 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1135 ASSERT_TRUE(vertex_buffer);
1136
1137 desc->SetSampleCount(SampleCount::kCount4);
1138 desc->SetStencilAttachmentDescriptors(std::nullopt);
1139
1140 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1141 auto boston = CreateTextureForFixture("boston.jpg");
1142 ASSERT_TRUE(bridge && boston);
1143 const std::unique_ptr<const Sampler>& sampler =
1144 context->GetSamplerLibrary()->GetSampler({});
1145 ASSERT_TRUE(sampler);
1146
1147 static bool mirror = false;
1148 static int stencil_reference_write = 0xFF;
1149 static int stencil_reference_read = 0x1;
1150 std::vector<uint8_t> stencil_contents;
1151 static int last_stencil_contents_reference_value = 0;
1152 static int current_front_compare =
1153 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1154 static int current_back_compare =
1155 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1156
1157 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
1158 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
1159 auto buffer = context->CreateCommandBuffer();
1160 if (!buffer) {
1161 return false;
1162 }
1163 buffer->SetLabel("Playground Command Buffer");
1164
1165 {
1166 // Configure the stencil attachment for the test.
1167 RenderTarget::AttachmentConfig stencil_config;
1168 stencil_config.load_action = LoadAction::kLoad;
1169 stencil_config.store_action = StoreAction::kDontCare;
1170 stencil_config.storage_mode = StorageMode::kHostVisible;
1171 render_target.SetupDepthStencilAttachments(
1172 *context, *context->GetResourceAllocator(),
1173 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1174 // Fill the stencil buffer with an checkerboard pattern.
1175 const auto target_width = render_target.GetRenderTargetSize().width;
1176 const auto target_height = render_target.GetRenderTargetSize().height;
1177 const size_t target_size = target_width * target_height;
1178 if (stencil_contents.size() != target_size ||
1179 last_stencil_contents_reference_value != stencil_reference_write) {
1180 stencil_contents.resize(target_size);
1181 last_stencil_contents_reference_value = stencil_reference_write;
1182 for (int y = 0; y < target_height; y++) {
1183 for (int x = 0; x < target_width; x++) {
1184 const auto index = y * target_width + x;
1185 const auto kCheckSize = 64;
1186 const auto value =
1187 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1188 stencil_reference_write;
1189 stencil_contents[index] = value;
1190 }
1191 }
1192 }
1193 if (!render_target.GetStencilAttachment()->texture->SetContents(
1194 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1195 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1196 return false;
1197 }
1198 auto pass = buffer->CreateRenderPass(render_target);
1199 if (!pass) {
1200 return false;
1201 }
1202 pass->SetLabel("Stencil Buffer");
1203 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1204 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1205 0xFF);
1206 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1207 0xFF);
1208 ImGui::Checkbox("Back face mode", &mirror);
1209 ImGui::ListBox("Front face compare function", &current_front_compare,
1210 CompareFunctionUI().labels(), CompareFunctionUI().size());
1211 ImGui::ListBox("Back face compare function", &current_back_compare,
1212 CompareFunctionUI().labels(), CompareFunctionUI().size());
1213 ImGui::End();
1214
1215 StencilAttachmentDescriptor front;
1216 front.stencil_compare =
1217 CompareFunctionUI().FunctionOf(current_front_compare);
1218 StencilAttachmentDescriptor back;
1219 back.stencil_compare =
1220 CompareFunctionUI().FunctionOf(current_back_compare);
1221 desc->SetStencilAttachmentDescriptors(front, back);
1222 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1223
1224 assert(pipeline && pipeline->IsValid());
1225
1226 pass->SetCommandLabel("Box");
1227 pass->SetPipeline(pipeline);
1228 pass->SetStencilReference(stencil_reference_read);
1229 pass->SetVertexBuffer(vertex_buffer);
1230
1231 VS::UniformBuffer uniforms;
1232 EXPECT_EQ(pass->GetOrthographicTransform(),
1233 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1234 uniforms.mvp = pass->GetOrthographicTransform() *
1235 Matrix::MakeScale(GetContentScale());
1236 if (mirror) {
1237 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1238 }
1239 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1240
1241 FS::FrameInfo frame_info;
1242 frame_info.current_time = GetSecondsElapsed();
1243 frame_info.cursor_position = GetCursorPosition();
1244 frame_info.window_size.x = GetWindowSize().width;
1245 frame_info.window_size.y = GetWindowSize().height;
1246
1247 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1248 FS::BindContents1(*pass, boston, sampler);
1249 FS::BindContents2(*pass, bridge, sampler);
1250 if (!pass->Draw().ok()) {
1251 return false;
1252 }
1253 pass->EncodeCommands();
1254 }
1255
1256 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1257 return false;
1258 }
1259 host_buffer->Reset();
1260 return true;
1261 };
1262 OpenPlaygroundHere(callback);
1263}
static unsigned mirror(SkFixed fx, int max)
CompareFunction FunctionOf(int index) const
int IndexOf(CompareFunction func) const
static const CompareFunctionUIData & CompareFunctionUI()

◆ TEST_P() [412/435]

impeller::testing::TEST_P ( RendererTest  ,
TheImpeller   
)

Definition at line 822 of file renderer_unittests.cc.

822 {
823 using VS = ImpellerVertexShader;
824 using FS = ImpellerFragmentShader;
825
826 auto context = GetContext();
827 auto pipeline_descriptor =
829 ASSERT_TRUE(pipeline_descriptor.has_value());
830 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
831 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
832 auto pipeline =
833 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
834 ASSERT_TRUE(pipeline && pipeline->IsValid());
835
836 auto blue_noise = CreateTextureForFixture("blue_noise.png");
837 SamplerDescriptor noise_sampler_desc;
838 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
839 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
840 const std::unique_ptr<const Sampler>& noise_sampler =
841 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
842
843 auto cube_map = CreateTextureCubeForFixture(
844 {"table_mountain_px.png", "table_mountain_nx.png",
845 "table_mountain_py.png", "table_mountain_ny.png",
846 "table_mountain_pz.png", "table_mountain_nz.png"});
847 const std::unique_ptr<const Sampler>& cube_map_sampler =
848 context->GetSamplerLibrary()->GetSampler({});
849 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
850
851 SinglePassCallback callback = [&](RenderPass& pass) {
852 auto size = pass.GetRenderTargetSize();
853
854 pass.SetPipeline(pipeline);
855 pass.SetCommandLabel("Impeller SDF scene");
856 VertexBufferBuilder<VS::PerVertexData> builder;
857 builder.AddVertices({{Point()},
858 {Point(0, size.height)},
859 {Point(size.width, 0)},
860 {Point(size.width, 0)},
861 {Point(0, size.height)},
862 {Point(size.width, size.height)}});
863 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
864
865 VS::FrameInfo frame_info;
866 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
867 frame_info.mvp = pass.GetOrthographicTransform();
868 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
869
870 FS::FragInfo fs_uniform;
871 fs_uniform.texture_size = Point(size);
872 fs_uniform.time = GetSecondsElapsed();
873 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
874 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
875 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
876
877 pass.Draw().ok();
878 host_buffer->Reset();
879 return true;
880 };
881 OpenPlaygroundHere(callback);
882}
SamplerAddressMode width_address_mode
SamplerAddressMode height_address_mode

◆ TEST_P() [413/435]

impeller::testing::TEST_P ( RendererTest  ,
VertexBufferBuilder   
)

Definition at line 1043 of file renderer_unittests.cc.

1043 {
1044 // Does not create index buffer if one is provided.
1045 using VS = BoxFadeVertexShader;
1047 vertex_builder.SetLabel("Box");
1048 vertex_builder.AddVertices({
1049 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1050 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1051 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1052 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1053 });
1054 vertex_builder.AppendIndex(0);
1055 vertex_builder.AppendIndex(1);
1056 vertex_builder.AppendIndex(2);
1057 vertex_builder.AppendIndex(1);
1058 vertex_builder.AppendIndex(2);
1059 vertex_builder.AppendIndex(3);
1060
1061 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1062 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1063}

◆ TEST_P() [414/435]

impeller::testing::TEST_P ( RenderTargetCacheTest  ,
CachedTextureGetsNewAttachmentConfig   
)

Definition at line 90 of file render_target_cache_unittests.cc.

90 {
91 auto render_target_cache =
92 RenderTargetCache(GetContext()->GetResourceAllocator());
93
94 render_target_cache.Start();
95 RenderTarget::AttachmentConfig color_attachment_config =
96 RenderTarget::kDefaultColorAttachmentConfig;
97 RenderTarget target1 = render_target_cache.CreateOffscreen(
98 *GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
99 render_target_cache.End();
100
101 render_target_cache.Start();
102 color_attachment_config.clear_color = Color::Red();
103 RenderTarget target2 = render_target_cache.CreateOffscreen(
104 *GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
105 render_target_cache.End();
106
107 auto color1 = target1.GetColorAttachments().find(0)->second;
108 auto color2 = target2.GetColorAttachments().find(0)->second;
109 // The second color attachment should reuse the first attachment's texture
110 // but with attributes from the second AttachmentConfig.
111 EXPECT_EQ(color2.texture, color1.texture);
112 EXPECT_EQ(color2.clear_color, Color::Red());
113}
An implementation of the [RenderTargetAllocator] that caches all allocated texture data for one frame...

◆ TEST_P() [415/435]

impeller::testing::TEST_P ( RenderTargetCacheTest  ,
CachesUsedTexturesAcrossFrames   
)

Definition at line 51 of file render_target_cache_unittests.cc.

51 {
52 auto render_target_cache =
53 RenderTargetCache(GetContext()->GetResourceAllocator());
54
55 render_target_cache.Start();
56 // Create two render targets of the same exact size/shape. Both should be
57 // marked as used this frame, so the cached data set will contain two.
58 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
59 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
60
61 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
62
63 render_target_cache.End();
64 render_target_cache.Start();
65
66 // Next frame, only create one texture. The set will still contain two,
67 // but one will be removed at the end of the frame.
68 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
69 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
70
71 render_target_cache.End();
72 EXPECT_EQ(render_target_cache.CachedTextureCount(), 1u);
73}

◆ TEST_P() [416/435]

impeller::testing::TEST_P ( RenderTargetCacheTest  ,
CreateWithEmptySize   
)

Definition at line 115 of file render_target_cache_unittests.cc.

115 {
116 auto render_target_cache =
117 RenderTargetCache(GetContext()->GetResourceAllocator());
118
119 render_target_cache.Start();
120 RenderTarget empty_target =
121 render_target_cache.CreateOffscreen(*GetContext(), {100, 0}, 1);
122 RenderTarget empty_target_msaa =
123 render_target_cache.CreateOffscreenMSAA(*GetContext(), {0, 0}, 1);
124 render_target_cache.End();
125
126 {
127 ScopedValidationDisable disable_validation;
128 EXPECT_FALSE(empty_target.IsValid());
129 EXPECT_FALSE(empty_target_msaa.IsValid());
130 }
131}

◆ TEST_P() [417/435]

impeller::testing::TEST_P ( RenderTargetCacheTest  ,
DoesNotPersistFailedAllocations   
)

Definition at line 75 of file render_target_cache_unittests.cc.

75 {
77 auto allocator = std::make_shared<TestAllocator>();
78 auto render_target_cache = RenderTargetCache(allocator);
79
80 render_target_cache.Start();
81 allocator->should_fail = true;
82
83 auto render_target =
84 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
85
86 EXPECT_FALSE(render_target.IsValid());
87 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
88}

◆ TEST_P() [418/435]

impeller::testing::TEST_P ( RuntimeStageTest  ,
CanCreatePipelineFromRuntimeStage   
)

Definition at line 263 of file runtime_stage_unittests.cc.

263 {
264 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
265 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
266
267 ASSERT_TRUE(stage);
268 ASSERT_NE(stage, nullptr);
269 ASSERT_TRUE(RegisterStage(*stage));
270 auto library = GetContext()->GetShaderLibrary();
271 using VS = RuntimeEffectVertexShader;
273 desc.SetLabel("Runtime Stage InkSparkle");
274 desc.AddStageEntrypoint(
275 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
276 desc.AddStageEntrypoint(
277 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
278 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
279 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
280 VS::kInterleavedBufferLayout);
281
282 std::array<DescriptorSetLayout, 2> descriptor_set_layouts = {
283 VS::kDescriptorSetLayouts[0],
285 .binding = 64u,
286 .descriptor_type = DescriptorType::kUniformBuffer,
287 .shader_stage = ShaderStage::kFragment,
288 },
289 };
290 vertex_descriptor->RegisterDescriptorSetLayouts(descriptor_set_layouts);
291
292 desc.SetVertexDescriptor(std::move(vertex_descriptor));
293 ColorAttachmentDescriptor color0;
294 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
295 StencilAttachmentDescriptor stencil0;
296 stencil0.stencil_compare = CompareFunction::kEqual;
297 desc.SetColorAttachmentDescriptor(0u, color0);
298 desc.SetStencilAttachmentDescriptors(stencil0);
299 const auto stencil_fmt =
300 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
301 desc.SetStencilPixelFormat(stencil_fmt);
302 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
303 ASSERT_NE(pipeline, nullptr);
304}

◆ TEST_P() [419/435]

impeller::testing::TEST_P ( RuntimeStageTest  ,
CanReadUniforms   
)

Definition at line 54 of file runtime_stage_unittests.cc.

54 {
55 const std::shared_ptr<fml::Mapping> fixture =
56 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
57 ASSERT_TRUE(fixture);
58 ASSERT_GT(fixture->GetSize(), 0u);
59 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
60 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
61
62 ASSERT_TRUE(stage->IsValid());
63 switch (GetBackend()) {
64 case PlaygroundBackend::kMetal:
65 [[fallthrough]];
66 case PlaygroundBackend::kOpenGLES: {
67 ASSERT_EQ(stage->GetUniforms().size(), 17u);
68 {
69 auto uni = stage->GetUniform("u_color");
70 ASSERT_NE(uni, nullptr);
71 EXPECT_EQ(uni->dimensions.rows, 4u);
72 EXPECT_EQ(uni->dimensions.cols, 1u);
73 EXPECT_EQ(uni->location, 0u);
74 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
75 }
76 {
77 auto uni = stage->GetUniform("u_alpha");
78 ASSERT_NE(uni, nullptr);
79 EXPECT_EQ(uni->dimensions.rows, 1u);
80 EXPECT_EQ(uni->dimensions.cols, 1u);
81 EXPECT_EQ(uni->location, 1u);
82 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
83 }
84 {
85 auto uni = stage->GetUniform("u_sparkle_color");
86 ASSERT_NE(uni, nullptr);
87 EXPECT_EQ(uni->dimensions.rows, 4u);
88 EXPECT_EQ(uni->dimensions.cols, 1u);
89 EXPECT_EQ(uni->location, 2u);
90 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
91 }
92 {
93 auto uni = stage->GetUniform("u_sparkle_alpha");
94 ASSERT_NE(uni, nullptr);
95 EXPECT_EQ(uni->dimensions.rows, 1u);
96 EXPECT_EQ(uni->dimensions.cols, 1u);
97 EXPECT_EQ(uni->location, 3u);
98 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
99 }
100 {
101 auto uni = stage->GetUniform("u_blur");
102 ASSERT_NE(uni, nullptr);
103 EXPECT_EQ(uni->dimensions.rows, 1u);
104 EXPECT_EQ(uni->dimensions.cols, 1u);
105 EXPECT_EQ(uni->location, 4u);
106 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
107 }
108 {
109 auto uni = stage->GetUniform("u_radius_scale");
110 ASSERT_NE(uni, nullptr);
111 EXPECT_EQ(uni->dimensions.rows, 1u);
112 EXPECT_EQ(uni->dimensions.cols, 1u);
113 EXPECT_EQ(uni->location, 6u);
114 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
115 }
116 {
117 auto uni = stage->GetUniform("u_max_radius");
118 ASSERT_NE(uni, nullptr);
119 EXPECT_EQ(uni->dimensions.rows, 1u);
120 EXPECT_EQ(uni->dimensions.cols, 1u);
121 EXPECT_EQ(uni->location, 7u);
122 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
123 }
124 {
125 auto uni = stage->GetUniform("u_resolution_scale");
126 ASSERT_NE(uni, nullptr);
127 EXPECT_EQ(uni->dimensions.rows, 2u);
128 EXPECT_EQ(uni->dimensions.cols, 1u);
129 EXPECT_EQ(uni->location, 8u);
130 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
131 }
132 {
133 auto uni = stage->GetUniform("u_noise_scale");
134 ASSERT_NE(uni, nullptr);
135 EXPECT_EQ(uni->dimensions.rows, 2u);
136 EXPECT_EQ(uni->dimensions.cols, 1u);
137 EXPECT_EQ(uni->location, 9u);
138 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
139 }
140 {
141 auto uni = stage->GetUniform("u_noise_phase");
142 ASSERT_NE(uni, nullptr);
143 EXPECT_EQ(uni->dimensions.rows, 1u);
144 EXPECT_EQ(uni->dimensions.cols, 1u);
145 EXPECT_EQ(uni->location, 10u);
146 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
147 }
148
149 {
150 auto uni = stage->GetUniform("u_circle1");
151 ASSERT_NE(uni, nullptr);
152 EXPECT_EQ(uni->dimensions.rows, 2u);
153 EXPECT_EQ(uni->dimensions.cols, 1u);
154 EXPECT_EQ(uni->location, 11u);
155 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
156 }
157 {
158 auto uni = stage->GetUniform("u_circle2");
159 ASSERT_NE(uni, nullptr);
160 EXPECT_EQ(uni->dimensions.rows, 2u);
161 EXPECT_EQ(uni->dimensions.cols, 1u);
162 EXPECT_EQ(uni->location, 12u);
163 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
164 }
165 {
166 auto uni = stage->GetUniform("u_circle3");
167 ASSERT_NE(uni, nullptr);
168 EXPECT_EQ(uni->dimensions.rows, 2u);
169 EXPECT_EQ(uni->dimensions.cols, 1u);
170 EXPECT_EQ(uni->location, 13u);
171 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
172 }
173 {
174 auto uni = stage->GetUniform("u_rotation1");
175 ASSERT_NE(uni, nullptr);
176 EXPECT_EQ(uni->dimensions.rows, 2u);
177 EXPECT_EQ(uni->dimensions.cols, 1u);
178 EXPECT_EQ(uni->location, 14u);
179 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
180 }
181 {
182 auto uni = stage->GetUniform("u_rotation2");
183 ASSERT_NE(uni, nullptr);
184 EXPECT_EQ(uni->dimensions.rows, 2u);
185 EXPECT_EQ(uni->dimensions.cols, 1u);
186 EXPECT_EQ(uni->location, 15u);
187 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
188 }
189 {
190 auto uni = stage->GetUniform("u_rotation3");
191 ASSERT_NE(uni, nullptr);
192 EXPECT_EQ(uni->dimensions.rows, 2u);
193 EXPECT_EQ(uni->dimensions.cols, 1u);
194 EXPECT_EQ(uni->location, 16u);
195 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
196 }
197 break;
198 }
199 case PlaygroundBackend::kVulkan: {
200 EXPECT_EQ(stage->GetUniforms().size(), 1u);
201 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
202 ASSERT_TRUE(uni);
203 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
204 EXPECT_EQ(uni->struct_float_count, 32u);
205
206 // There are 36 4 byte chunks in the UBO: 32 for the 32 floats, and 4 for
207 // padding. Initialize a vector as if they'll all be floats, then manually
208 // set the few padding bytes. If the shader changes, the padding locations
209 // will change as well. For example, if `u_alpha` was moved to the end,
210 // three bytes of padding could potentially be dropped - or if some of the
211 // scalar floats were changed to vec2 or vec4s, or if any vec3s are
212 // introduced.
213 // This means 36 * 4 = 144 bytes total.
214
215 EXPECT_EQ(uni->GetSize(), 144u);
216 std::vector<uint8_t> layout(uni->GetSize() / sizeof(float), 1);
217 layout[5] = 0;
218 layout[6] = 0;
219 layout[7] = 0;
220 layout[23] = 0;
221
222 EXPECT_THAT(uni->struct_layout, ::testing::ElementsAreArray(layout));
223 break;
224 }
225 }
226}

◆ TEST_P() [420/435]

impeller::testing::TEST_P ( RuntimeStageTest  ,
CanReadValidBlob   
)

Definition at line 28 of file runtime_stage_unittests.cc.

28 {
29 const std::shared_ptr<fml::Mapping> fixture =
30 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
31 ASSERT_TRUE(fixture);
32 ASSERT_GT(fixture->GetSize(), 0u);
33 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
34 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
35 ASSERT_TRUE(stage->IsValid());
36 ASSERT_EQ(stage->GetShaderStage(), RuntimeShaderStage::kFragment);
37}

◆ TEST_P() [421/435]

impeller::testing::TEST_P ( RuntimeStageTest  ,
CanRegisterStage   
)

Definition at line 228 of file runtime_stage_unittests.cc.

228 {
229 const std::shared_ptr<fml::Mapping> fixture =
230 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
231 ASSERT_TRUE(fixture);
232 ASSERT_GT(fixture->GetSize(), 0u);
233 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
234 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
235 ASSERT_TRUE(stage->IsValid());
236 std::promise<bool> registration;
237 auto future = registration.get_future();
238 auto library = GetContext()->GetShaderLibrary();
239 library->RegisterFunction(
240 stage->GetEntrypoint(), //
241 ToShaderStage(stage->GetShaderStage()), //
242 stage->GetCodeMapping(), //
243 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
244 reg.set_value(result);
245 }));
246 ASSERT_TRUE(future.get());
247 {
248 auto function =
249 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
250 ASSERT_NE(function, nullptr);
251 }
252
253 // Check if unregistering works.
254
255 library->UnregisterFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
256 {
257 auto function =
258 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
259 ASSERT_EQ(function, nullptr);
260 }
261}
Dart_NativeFunction function
Definition fuchsia.cc:51
internal::CopyableLambda< T > MakeCopyable(T lambda)
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)

◆ TEST_P() [422/435]

impeller::testing::TEST_P ( RuntimeStageTest  ,
CanRejectInvalidBlob   
)

Definition at line 39 of file runtime_stage_unittests.cc.

39 {
40 ScopedValidationDisable disable_validation;
41 const std::shared_ptr<fml::Mapping> fixture =
42 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
43 ASSERT_TRUE(fixture);
44 auto junk_allocation = std::make_shared<Allocation>();
45 ASSERT_TRUE(junk_allocation->Truncate(fixture->GetSize(), false));
46 // Not meant to be secure. Just reject obviously bad blobs using magic
47 // numbers.
48 ::memset(junk_allocation->GetBuffer(), 127, junk_allocation->GetLength());
49 auto stages = RuntimeStage::DecodeRuntimeStages(
50 CreateMappingFromAllocation(junk_allocation));
51 ASSERT_FALSE(stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())]);
52}
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Definition allocation.cc:99

◆ TEST_P() [423/435]

impeller::testing::TEST_P ( RuntimeStageTest  ,
ContainsExpectedShaderTypes   
)

Definition at line 306 of file runtime_stage_unittests.cc.

306 {
307 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
308 // Right now, SkSL gets implicitly bundled regardless of what the build rule
309 // for this test requested. After
310 // https://github.com/flutter/flutter/issues/138919, this may require a build
311 // rule change or a new test.
312 EXPECT_TRUE(stages[RuntimeStageBackend::kSkSL]);
313
314 EXPECT_TRUE(stages[RuntimeStageBackend::kOpenGLES]);
315 EXPECT_TRUE(stages[RuntimeStageBackend::kMetal]);
316 EXPECT_TRUE(stages[RuntimeStageBackend::kVulkan]);
317}

◆ TEST_P() [424/435]

impeller::testing::TEST_P ( TypographerTest  ,
CanConvertTextBlob   
)

Definition at line 41 of file typographer_unittests.cc.

41 {
44 "the quick brown fox jumped over the lazy dog.", font);
45 ASSERT_TRUE(blob);
47 ASSERT_EQ(frame->GetRunCount(), 1u);
48 for (const auto& run : frame->GetRuns()) {
49 ASSERT_TRUE(run.IsValid());
50 ASSERT_EQ(run.GetGlyphCount(), 45u);
51 }
52}
Definition run.py:1

◆ TEST_P() [425/435]

impeller::testing::TEST_P ( TypographerTest  ,
CanCreateGlyphAtlas   
)

Definition at line 59 of file typographer_unittests.cc.

59 {
60 auto context = TypographerContextSkia::Make();
61 auto atlas_context = context->CreateGlyphAtlasContext();
62 ASSERT_TRUE(context && context->IsValid());
64 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
65 ASSERT_TRUE(blob);
66 auto atlas = CreateGlyphAtlas(
67 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
68 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
69 ASSERT_NE(atlas, nullptr);
70 ASSERT_NE(atlas->GetTexture(), nullptr);
71 ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
72 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
73
74 std::optional<impeller::ScaledFont> first_scaled_font;
75 std::optional<impeller::Glyph> first_glyph;
76 Rect first_rect;
77 atlas->IterateGlyphs([&](const ScaledFont& scaled_font, const Glyph& glyph,
78 const Rect& rect) -> bool {
79 first_scaled_font = scaled_font;
80 first_glyph = glyph;
81 first_rect = rect;
82 return false;
83 });
84
85 ASSERT_TRUE(first_scaled_font.has_value());
86 ASSERT_TRUE(atlas
87 ->FindFontGlyphBounds(
88 {first_scaled_font.value(), first_glyph.value()})
89 .has_value());
90}
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
The glyph index in the typeface.
Definition glyph.h:20
A font and a scale. Used as a key that represents a typeface within a glyph atlas.

◆ TEST_P() [426/435]

impeller::testing::TEST_P ( TypographerTest  ,
CanCreateRenderContext   
)

Definition at line 54 of file typographer_unittests.cc.

54 {
55 auto context = TypographerContextSkia::Make();
56 ASSERT_TRUE(context && context->IsValid());
57}

◆ TEST_P() [427/435]

impeller::testing::TEST_P ( TypographerTest  ,
GlyphAtlasIsRecycledIfUnchanged   
)

Definition at line 147 of file typographer_unittests.cc.

147 {
148 auto context = TypographerContextSkia::Make();
149 auto atlas_context = context->CreateGlyphAtlasContext();
150 ASSERT_TRUE(context && context->IsValid());
152 auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
153 ASSERT_TRUE(blob);
154 auto atlas = CreateGlyphAtlas(
155 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
156 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
157 ASSERT_NE(atlas, nullptr);
158 ASSERT_NE(atlas->GetTexture(), nullptr);
159 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
160
161 // now attempt to re-create an atlas with the same text blob.
162
163 auto next_atlas = CreateGlyphAtlas(
164 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
165 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
166 ASSERT_EQ(atlas, next_atlas);
167 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
168}

◆ TEST_P() [428/435]

impeller::testing::TEST_P ( TypographerTest  ,
GlyphAtlasTextureIsRecreatedIfTypeChanges   
)

Definition at line 247 of file typographer_unittests.cc.

247 {
248 auto context = TypographerContextSkia::Make();
249 auto atlas_context = context->CreateGlyphAtlasContext();
250 ASSERT_TRUE(context && context->IsValid());
252 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
253 ASSERT_TRUE(blob);
254 auto atlas = CreateGlyphAtlas(
255 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
256 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
257 auto old_packer = atlas_context->GetRectPacker();
258
259 ASSERT_NE(atlas, nullptr);
260 ASSERT_NE(atlas->GetTexture(), nullptr);
261 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
262
263 auto* first_texture = atlas->GetTexture().get();
264
265 // now create a new glyph atlas with an identical blob,
266 // but change the type.
267
268 auto blob2 = SkTextBlob::MakeFromString("spooky 1", sk_font);
269 auto next_atlas = CreateGlyphAtlas(
270 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 1.0f,
271 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
272 ASSERT_NE(atlas, next_atlas);
273 auto* second_texture = next_atlas->GetTexture().get();
274
275 auto new_packer = atlas_context->GetRectPacker();
276
277 ASSERT_NE(second_texture, first_texture);
278 ASSERT_NE(old_packer, new_packer);
279}

◆ TEST_P() [429/435]

impeller::testing::TEST_P ( TypographerTest  ,
GlyphAtlasTextureIsRecycledIfUnchanged   
)

Definition at line 214 of file typographer_unittests.cc.

214 {
215 auto context = TypographerContextSkia::Make();
216 auto atlas_context = context->CreateGlyphAtlasContext();
217 ASSERT_TRUE(context && context->IsValid());
219 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
220 ASSERT_TRUE(blob);
221 auto atlas = CreateGlyphAtlas(
222 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
223 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
224 auto old_packer = atlas_context->GetRectPacker();
225
226 ASSERT_NE(atlas, nullptr);
227 ASSERT_NE(atlas->GetTexture(), nullptr);
228 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
229
230 auto* first_texture = atlas->GetTexture().get();
231
232 // Now create a new glyph atlas with a nearly identical blob.
233
234 auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
235 auto next_atlas = CreateGlyphAtlas(
236 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
237 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
238 ASSERT_EQ(atlas, next_atlas);
239 auto* second_texture = next_atlas->GetTexture().get();
240
241 auto new_packer = atlas_context->GetRectPacker();
242
243 ASSERT_EQ(second_texture, first_texture);
244 ASSERT_EQ(old_packer, new_packer);
245}

◆ TEST_P() [430/435]

impeller::testing::TEST_P ( TypographerTest  ,
GlyphAtlasTextureIsRecycledWhenContentsAreNotRecreated   
)

Definition at line 341 of file typographer_unittests.cc.

342 {
343 auto context = TypographerContextSkia::Make();
344 auto atlas_context = context->CreateGlyphAtlasContext();
345 ASSERT_TRUE(context && context->IsValid());
347 auto blob = SkTextBlob::MakeFromString("ABCDEFGHIJKLMNOPQRSTUVQXYZ123456789",
348 sk_font);
349 ASSERT_TRUE(blob);
350 auto atlas = CreateGlyphAtlas(
351 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 32.0f,
352 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
353 auto old_packer = atlas_context->GetRectPacker();
354
355 ASSERT_NE(atlas, nullptr);
356 ASSERT_NE(atlas->GetTexture(), nullptr);
357 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
358
359 auto* first_texture = atlas->GetTexture().get();
360
361 // Now create a new glyph atlas with a completely different textblob.
362 // everything should be different except for the underlying atlas texture.
363
364 auto blob2 = SkTextBlob::MakeFromString("abcdefghijklmnopqrstuvwxyz123456789",
365 sk_font);
366 auto next_atlas = CreateGlyphAtlas(
367 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 32.0f,
368 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
369 ASSERT_NE(atlas, next_atlas);
370 auto* second_texture = next_atlas->GetTexture().get();
371
372 auto new_packer = atlas_context->GetRectPacker();
373
374 ASSERT_NE(second_texture, first_texture);
375 ASSERT_NE(old_packer, new_packer);
376}

◆ TEST_P() [431/435]

impeller::testing::TEST_P ( TypographerTest  ,
GlyphAtlasWithLotsOfdUniqueGlyphSize   
)

Definition at line 170 of file typographer_unittests.cc.

170 {
171 auto context = TypographerContextSkia::Make();
172 auto atlas_context = context->CreateGlyphAtlasContext();
173 ASSERT_TRUE(context && context->IsValid());
174
175 const char* test_string =
176 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
177 "2134567890-=!@#$%^&*()_+"
178 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›fifl‡°·‚—±Œ„´‰Á¨Ø∏”’/"
179 "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
180
182 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
183 ASSERT_TRUE(blob);
184
185 FontGlyphMap font_glyph_map;
186 size_t size_count = 8;
187 for (size_t index = 0; index < size_count; index += 1) {
188 MakeTextFrameFromTextBlobSkia(blob)->CollectUniqueFontGlyphPairs(
189 font_glyph_map, 0.6 * index);
190 };
191 auto atlas =
192 context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
193 atlas_context, font_glyph_map);
194 ASSERT_NE(atlas, nullptr);
195 ASSERT_NE(atlas->GetTexture(), nullptr);
196
197 std::set<uint16_t> unique_glyphs;
198 std::vector<uint16_t> total_glyphs;
199 atlas->IterateGlyphs(
200 [&](const ScaledFont& scaled_font, const Glyph& glyph, const Rect& rect) {
201 unique_glyphs.insert(glyph.index);
202 total_glyphs.push_back(glyph.index);
203 return true;
204 });
205
206 EXPECT_EQ(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
207 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
208
209 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
210 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
211 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
212}
int width() const
Definition SkImage.h:285
int height() const
Definition SkImage.h:291
uint16_t index
Definition glyph.h:26

◆ TEST_P() [432/435]

impeller::testing::TEST_P ( TypographerTest  ,
GlyphAtlasWithOddUniqueGlyphSize   
)

Definition at line 130 of file typographer_unittests.cc.

130 {
131 auto context = TypographerContextSkia::Make();
132 auto atlas_context = context->CreateGlyphAtlasContext();
133 ASSERT_TRUE(context && context->IsValid());
135 auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
136 ASSERT_TRUE(blob);
137 auto atlas = CreateGlyphAtlas(
138 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
139 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
140 ASSERT_NE(atlas, nullptr);
141 ASSERT_NE(atlas->GetTexture(), nullptr);
142
143 ASSERT_EQ(atlas->GetTexture()->GetSize().width,
144 atlas->GetTexture()->GetSize().height);
145}

◆ TEST_P() [433/435]

impeller::testing::TEST_P ( TypographerTest  ,
LazyAtlasTracksColor   
)

Definition at line 92 of file typographer_unittests.cc.

92 {
93#if FML_OS_MACOSX
94 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
95#else
96 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
97#endif
98 ASSERT_TRUE(mapping);
100 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
102
103 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
104 ASSERT_TRUE(blob);
106
107 ASSERT_FALSE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
108
109 LazyGlyphAtlas lazy_atlas(TypographerContextSkia::Make());
110
111 lazy_atlas.AddTextFrame(*frame, 1.0f);
112
114 SkTextBlob::MakeFromString("😀 ", emoji_font));
115
116 ASSERT_TRUE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
117
118 lazy_atlas.AddTextFrame(*frame, 1.0f);
119
120 // Creates different atlases for color and red bitmap.
121 auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
122 *GetContext(), GlyphAtlas::Type::kColorBitmap);
123
124 auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
125 *GetContext(), GlyphAtlas::Type::kAlphaBitmap);
126
127 ASSERT_FALSE(color_atlas == bitmap_atlas);
128}

◆ TEST_P() [434/435]

impeller::testing::TEST_P ( TypographerTest  ,
MaybeHasOverlapping   
)

Definition at line 281 of file typographer_unittests.cc.

281 {
283 sk_sp<SkTypeface> typeface =
284 font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
285 SkFont sk_font(typeface, 0.5f);
286
287 auto frame =
289 // Single character has no overlapping
290 ASSERT_FALSE(frame->MaybeHasOverlapping());
291
292 auto frame_2 = MakeTextFrameFromTextBlobSkia(
293 SkTextBlob::MakeFromString("123456789", sk_font));
294 ASSERT_FALSE(frame_2->MaybeHasOverlapping());
295}
static constexpr SkFontStyle Normal()
Definition SkFontStyle.h:66

◆ TEST_P() [435/435]

impeller::testing::TEST_P ( TypographerTest  ,
RectanglePackerAddsNonoverlapingRectangles   
)

Definition at line 297 of file typographer_unittests.cc.

297 {
298 auto packer = RectanglePacker::Factory(200, 100);
299 ASSERT_NE(packer, nullptr);
300 ASSERT_EQ(packer->percentFull(), 0);
301
302 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
303
304 IPoint16 first_output = {-1, -1}; // Fill with sentinel values
305 ASSERT_TRUE(packer->addRect(20, 20, &first_output));
306 // Make sure the rectangle is placed such that it is inside the bounds of
307 // the packer's area.
308 const SkIRect first_rect =
309 SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
310 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
311
312 // Initial area was 200 x 100 = 20_000
313 // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
314 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.02));
315
316 IPoint16 second_output = {-1, -1};
317 ASSERT_TRUE(packer->addRect(140, 90, &second_output));
318 const SkIRect second_rect =
319 SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
320 // Make sure the rectangle is placed such that it is inside the bounds of
321 // the packer's area but not in the are of the first rectangle.
322 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
323 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
324
325 // We added another 90 x 140 = 12_600 units, now taking us to 13_000
326 // 13_000 / 20_000 == 0.65 == 65%
327 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.65));
328
329 // There's enough area to add this rectangle, but no space big enough for
330 // the 50 units of width.
331 IPoint16 output;
332 ASSERT_FALSE(packer->addRect(50, 50, &output));
333 // Should be unchanged.
334 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.65));
335
336 packer->reset();
337 // Should be empty now.
338 ASSERT_EQ(packer->percentFull(), 0);
339}
bool NumberNear(double a, double b)
Definition assertions.h:13
static bool Intersects(const SkIRect &a, const SkIRect &b)
Definition SkRect.h:535
int16_t y() const
int16_t x() const

◆ toColor()

flutter::DlColor impeller::testing::toColor ( const float *  components)

Definition at line 41 of file dl_unittests.cc.

41 {
42 return flutter::DlColor(Color::ToIColor(
43 Color(components[0], components[1], components[2], components[3])));
44}

Variable Documentation

◆ g_extensions

std::vector<const unsigned char*> impeller::testing::g_extensions
static

Definition at line 24 of file mock_gles.cc.

◆ g_mock_gles

std::weak_ptr<MockGLES> impeller::testing::g_mock_gles
static

Definition at line 20 of file mock_gles.cc.

◆ g_resolver

ProcTableGLES::Resolver impeller::testing::g_resolver
static

Definition at line 22 of file mock_gles.cc.

◆ g_test_lock

std::mutex impeller::testing::g_test_lock
static

Definition at line 18 of file mock_gles.cc.

◆ g_version

const unsigned char* impeller::testing::g_version
static

Definition at line 26 of file mock_gles.cc.

◆ golden_cubic_and_quad_points

std::vector<Point> impeller::testing::golden_cubic_and_quad_points

Definition at line 16 of file golden_paths.h.

16 {
17 {139.982, 19.5003}, {140.018, 20.4997}, {131.747, 19.8026},
18 {131.783, 20.802}, {131.715, 19.8048}, {131.815, 20.7998},
19 {123.622, 20.6102}, {123.721, 21.6053}, {123.59, 20.6145},
20 {123.753, 21.601}, {115.652, 21.9306}, {115.816, 22.9171},
21 {115.619, 21.9372}, {115.848, 22.9105}, {107.85, 23.7687},
22 {108.08, 24.742}, {107.817, 23.7777}, {108.113, 24.733},
23 {100.23, 26.1264}, {100.526, 27.0817}, {100.197, 26.1378},
24 {100.558, 27.0703}, {92.8037, 29.0025}, {93.165, 29.935},
25 {92.7736, 29.0154}, {93.1952, 29.9221}, {85.708, 32.3003},
26 {86.1296, 33.2071}, {85.68, 32.3144}, {86.1576, 33.193},
27 {78.8865, 36.008}, {79.3641, 36.8865}, {78.8588, 36.0242},
28 {79.3918, 36.8703}, {72.3485, 40.125}, {72.8815, 40.9711},
29 {72.3216, 40.1432}, {72.9084, 40.9529}, {66.1045, 44.6479},
30 {66.6913, 45.4577}, {66.0788, 44.6679}, {66.717, 45.4378},
31 {60.1632, 49.5711}, {60.8014, 50.341}, {60.139, 49.5924},
32 {60.8255, 50.3196}, {54.5317, 54.8864}, {55.2183, 55.6136},
33 {54.5094, 54.909}, {55.2406, 55.591}, {49.254, 60.5436},
34 {49.9853, 61.2257}, {49.2329, 60.5677}, {50.0063, 61.2016},
35 {44.3684, 66.5025}, {45.1418, 67.1364}, {44.3488, 66.5281},
36 {45.1614, 67.1108}, {39.8827, 72.7564}, {40.6954, 73.3391},
37 {39.8648, 72.7832}, {40.7133, 73.3123}, {35.8029, 79.297},
38 {36.6515, 79.8261}, {35.7869, 79.3246}, {36.6675, 79.7985},
39 {32.1328, 86.1144}, {33.0134, 86.5883}, {32.1188, 86.1424},
40 {33.0273, 86.5603}, {28.8739, 93.1973}, {29.7824, 93.6152},
41 {28.8613, 93.2272}, {29.795, 93.5853}, {26.0399, 100.583},
42 {26.9736, 100.941}, {26.0288, 100.615}, {26.9847, 100.908},
43 {23.7144, 108.15}, {24.6704, 108.444}, {23.7056, 108.183},
44 {24.6792, 108.411}, {21.9002, 115.886}, {22.8738, 116.115},
45 {21.8937, 115.919}, {22.8804, 116.082}, {20.5962, 123.779},
46 {21.5828, 123.942}, {20.592, 123.812}, {21.5871, 123.91},
47 {19.7985, 131.816}, {20.7936, 131.914}, {19.7964, 131.847},
48 {20.7957, 131.883}, {19.5003, 139.982}, {20.4997, 140.018},
49 {20.2883, 140.409}, {19.7117, 139.591}, {29.9421, 133.595},
50 {29.3655, 132.778}, {29.9544, 133.586}, {29.3532, 132.787},
51 {39.1905, 126.639}, {38.5894, 125.839}, {39.2039, 126.628},
52 {38.576, 125.85}, {47.9822, 119.545}, {47.3542, 118.767},
53 {47.9968, 119.533}, {47.3396, 118.779}, {56.2739, 112.316},
54 {55.6167, 111.562}, {56.2898, 112.302}, {55.6008, 111.577},
55 {64.0197, 104.952}, {63.3307, 104.228}, {64.0369, 104.935},
56 {63.3134, 104.245}, {71.1714, 97.4578}, {70.4479, 96.7675},
57 {71.1899, 97.4373}, {70.4294, 96.7879}, {77.6791, 89.8381},
58 {76.9187, 89.1887}, {77.6987, 89.8137}, {76.8991, 89.2131},
59 {83.4923, 82.1009}, {82.6928, 81.5003}, {83.5125, 82.0718},
60 {82.6725, 81.5293}, {88.5609, 74.2563}, {87.7209, 73.7138},
61 {88.5812, 74.2221}, {87.7007, 73.748}, {92.8369, 66.3173},
62 {91.9564, 65.8432}, {92.8562, 66.2772}, {91.9371, 65.8833},
63 {96.2756, 58.299}, {95.3564, 57.9051}, {96.2927, 58.253},
64 {95.3393, 57.951}, {98.8374, 50.2196}, {97.8841, 49.9176},
65 {98.8508, 50.1681}, {97.8708, 49.969}, {100.49, 42.0995},
66 {99.51, 41.9005}, {100.49, 42.0995}, {99.51, 41.9005},
67};

◆ kExtensions

auto const impeller::testing::kExtensions
Initial value:
= std::vector<const unsigned char*>{
(unsigned char*)"GL_KHR_debug"
}

Definition at line 46 of file mock_gles.cc.

46 {
47 (unsigned char*)"GL_KHR_debug" //
48};

◆ kFontFixture

constexpr std::string_view impeller::testing::kFontFixture
staticconstexpr
Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 811 of file aiks_unittests.cc.

◆ kMockResolverGLES

const ProcTableGLES::Resolver impeller::testing::kMockResolverGLES
Initial value:
= [](const char* name) {
if (strcmp(name, "glPopDebugGroupKHR") == 0) {
return reinterpret_cast<void*>(&mockPopDebugGroupKHR);
} else if (strcmp(name, "glPushDebugGroupKHR") == 0) {
return reinterpret_cast<void*>(&mockPushDebugGroupKHR);
} else if (strcmp(name, "glGetString") == 0) {
return reinterpret_cast<void*>(&mockGetString);
} else if (strcmp(name, "glGetStringi") == 0) {
return reinterpret_cast<void*>(&mockGetStringi);
} else if (strcmp(name, "glGetIntegerv") == 0) {
return reinterpret_cast<void*>(&mockGetIntegerv);
} else if (strcmp(name, "glGetError") == 0) {
return reinterpret_cast<void*>(&mockGetError);
} else if (strcmp(name, "glGenQueriesEXT") == 0) {
return reinterpret_cast<void*>(&mockGenQueriesEXT);
} else if (strcmp(name, "glBeginQueryEXT") == 0) {
return reinterpret_cast<void*>(&mockBeginQueryEXT);
} else if (strcmp(name, "glEndQueryEXT") == 0) {
return reinterpret_cast<void*>(&mockEndQueryEXT);
} else if (strcmp(name, "glDeleteQueriesEXT") == 0) {
return reinterpret_cast<void*>(&mockDeleteQueriesEXT);
} else if (strcmp(name, "glGetQueryObjectui64vEXT") == 0) {
return reinterpret_cast<void*>(mockGetQueryObjectui64vEXT);
} else if (strcmp(name, "glGetQueryObjectuivEXT") == 0) {
return reinterpret_cast<void*>(mockGetQueryObjectuivEXT);
} else {
return reinterpret_cast<void*>(&doNothing);
}
}
void mockDeleteQueriesEXT(GLsizei size, const GLuint *queries)
Definition mock_gles.cc:159
void mockGetQueryObjectuivEXT(GLuint id, GLenum target, GLuint *result)
Definition mock_gles.cc:143
GLenum mockGetError()
Definition mock_gles.cc:95
void mockPopDebugGroupKHR()
Definition mock_gles.cc:102
void mockGetIntegerv(GLenum name, int *value)
Definition mock_gles.cc:78
void mockGetQueryObjectui64vEXT(GLuint id, GLenum target, GLuint64 *result)
Definition mock_gles.cc:151
void mockPushDebugGroupKHR(GLenum source, GLuint id, GLsizei length, const GLchar *message)
Definition mock_gles.cc:109
void mockEndQueryEXT(GLuint id)
Definition mock_gles.cc:136
void mockGenQueriesEXT(GLsizei n, GLuint *ids)
Definition mock_gles.cc:119
void mockBeginQueryEXT(GLenum target, GLuint id)
Definition mock_gles.cc:129

Definition at line 180 of file mock_gles.cc.

180 {
181 if (strcmp(name, "glPopDebugGroupKHR") == 0) {
182 return reinterpret_cast<void*>(&mockPopDebugGroupKHR);
183 } else if (strcmp(name, "glPushDebugGroupKHR") == 0) {
184 return reinterpret_cast<void*>(&mockPushDebugGroupKHR);
185 } else if (strcmp(name, "glGetString") == 0) {
186 return reinterpret_cast<void*>(&mockGetString);
187 } else if (strcmp(name, "glGetStringi") == 0) {
188 return reinterpret_cast<void*>(&mockGetStringi);
189 } else if (strcmp(name, "glGetIntegerv") == 0) {
190 return reinterpret_cast<void*>(&mockGetIntegerv);
191 } else if (strcmp(name, "glGetError") == 0) {
192 return reinterpret_cast<void*>(&mockGetError);
193 } else if (strcmp(name, "glGenQueriesEXT") == 0) {
194 return reinterpret_cast<void*>(&mockGenQueriesEXT);
195 } else if (strcmp(name, "glBeginQueryEXT") == 0) {
196 return reinterpret_cast<void*>(&mockBeginQueryEXT);
197 } else if (strcmp(name, "glEndQueryEXT") == 0) {
198 return reinterpret_cast<void*>(&mockEndQueryEXT);
199 } else if (strcmp(name, "glDeleteQueriesEXT") == 0) {
200 return reinterpret_cast<void*>(&mockDeleteQueriesEXT);
201 } else if (strcmp(name, "glGetQueryObjectui64vEXT") == 0) {
202 return reinterpret_cast<void*>(mockGetQueryObjectui64vEXT);
203 } else if (strcmp(name, "glGetQueryObjectuivEXT") == 0) {
204 return reinterpret_cast<void*>(mockGetQueryObjectuivEXT);
205 } else {
206 return reinterpret_cast<void*>(&doNothing);
207 }
208};
const unsigned char * mockGetStringi(GLenum name, GLuint index)
Definition mock_gles.cc:66

◆ kMockShadingLanguageVersion

const auto impeller::testing::kMockShadingLanguageVersion = (unsigned char*)"GLSL ES 1.0"

Definition at line 45 of file mock_gles.cc.

◆ kMockVendor

auto const impeller::testing::kMockVendor = (unsigned char*)"MockGLES"

Definition at line 44 of file mock_gles.cc.

◆ kPaintVariations

const std::map<std::string, MaskBlurTestConfig> impeller::testing::kPaintVariations
static

Definition at line 368 of file aiks_blur_unittests.cc.

368 {
369 // 1. Normal style, translucent, zero sigma.
370 {"NormalTranslucentZeroSigma",
371 {.style = FilterContents::BlurStyle::kNormal,
372 .sigma = 0.0f,
373 .alpha = 0.5f}},
374 // 2. Normal style, translucent.
375 {"NormalTranslucent",
376 {.style = FilterContents::BlurStyle::kNormal,
377 .sigma = 8.0f,
378 .alpha = 0.5f}},
379 // 3. Solid style, translucent.
380 {"SolidTranslucent",
381 {.style = FilterContents::BlurStyle::kSolid,
382 .sigma = 8.0f,
383 .alpha = 0.5f}},
384 // 4. Solid style, opaque.
385 {"SolidOpaque",
386 {.style = FilterContents::BlurStyle::kSolid, .sigma = 8.0f}},
387 // 5. Solid style, translucent, color & image filtered.
388 {"SolidTranslucentWithFilters",
389 {.style = FilterContents::BlurStyle::kSolid,
390 .sigma = 8.0f,
391 .alpha = 0.5f,
392 .image_filter = ImageFilter::MakeBlur(Sigma{3},
393 Sigma{3},
394 FilterContents::BlurStyle::kNormal,
395 Entity::TileMode::kClamp),
396 .invert_colors = true}},
397 // 6. Solid style, translucent, exclusion blended.
398 {"SolidTranslucentExclusionBlend",
399 {.style = FilterContents::BlurStyle::kSolid,
400 .sigma = 8.0f,
401 .alpha = 0.5f,
402 .blend_mode = BlendMode::kExclusion}},
403 // 7. Inner style, translucent.
404 {"InnerTranslucent",
405 {.style = FilterContents::BlurStyle::kInner,
406 .sigma = 8.0f,
407 .alpha = 0.5f}},
408 // 8. Inner style, translucent, blurred.
409 {"InnerTranslucentWithBlurImageFilter",
410 {.style = FilterContents::BlurStyle::kInner,
411 .sigma = 8.0f,
412 .alpha = 0.5f,
413 .image_filter = ImageFilter::MakeBlur(Sigma{3},
414 Sigma{3},
415 FilterContents::BlurStyle::kNormal,
416 Entity::TileMode::kClamp)}},
417 // 9. Outer style, translucent.
418 {"OuterTranslucent",
419 {.style = FilterContents::BlurStyle::kOuter,
420 .sigma = 8.0f,
421 .alpha = 0.5f}},
422 // 10. Outer style, opaque, image filtered.
423 {"OuterOpaqueWithBlurImageFilter",
424 {.style = FilterContents::BlurStyle::kOuter,
425 .sigma = 8.0f,
426 .image_filter = ImageFilter::MakeBlur(Sigma{3},
427 Sigma{3},
428 FilterContents::BlurStyle::kNormal,
429 Entity::TileMode::kClamp)}},
430};