summaryrefslogtreecommitdiff
path: root/libs/hwui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/.clang-format10
-rw-r--r--libs/hwui/AmbientShadow.cpp99
-rw-r--r--libs/hwui/AmbientShadow.h14
-rw-r--r--libs/hwui/Android.bp76
-rw-r--r--libs/hwui/AnimationContext.cpp23
-rw-r--r--libs/hwui/AnimationContext.h8
-rw-r--r--libs/hwui/Animator.cpp177
-rw-r--r--libs/hwui/Animator.h36
-rw-r--r--libs/hwui/AnimatorManager.cpp27
-rw-r--r--libs/hwui/AnimatorManager.h5
-rw-r--r--libs/hwui/BakedOpDispatcher.cpp302
-rw-r--r--libs/hwui/BakedOpDispatcher.h15
-rw-r--r--libs/hwui/BakedOpRenderer.cpp62
-rw-r--r--libs/hwui/BakedOpRenderer.h25
-rw-r--r--libs/hwui/BakedOpState.cpp60
-rw-r--r--libs/hwui/BakedOpState.h70
-rw-r--r--libs/hwui/Caches.cpp68
-rw-r--r--libs/hwui/Caches.h35
-rw-r--r--libs/hwui/CanvasProperty.h2
-rw-r--r--libs/hwui/CanvasState.cpp39
-rw-r--r--libs/hwui/CanvasState.h44
-rw-r--r--libs/hwui/ClipArea.cpp192
-rw-r--r--libs/hwui/ClipArea.h82
-rw-r--r--libs/hwui/DamageAccumulator.cpp51
-rw-r--r--libs/hwui/DamageAccumulator.h3
-rw-r--r--libs/hwui/Debug.h6
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp34
-rw-r--r--libs/hwui/DeferredLayerUpdater.h36
-rw-r--r--libs/hwui/DeviceInfo.cpp34
-rw-r--r--libs/hwui/DeviceInfo.h6
-rw-r--r--libs/hwui/DisplayList.cpp13
-rw-r--r--libs/hwui/DisplayList.h24
-rw-r--r--libs/hwui/Extensions.cpp11
-rw-r--r--libs/hwui/Extensions.h8
-rw-r--r--libs/hwui/FboCache.cpp7
-rw-r--r--libs/hwui/FboCache.h8
-rw-r--r--libs/hwui/FloatColor.h25
-rw-r--r--libs/hwui/FontRenderer.cpp149
-rw-r--r--libs/hwui/FontRenderer.h104
-rw-r--r--libs/hwui/FrameBuilder.cpp289
-rw-r--r--libs/hwui/FrameBuilder.h107
-rw-r--r--libs/hwui/FrameInfo.cpp40
-rw-r--r--libs/hwui/FrameInfo.h46
-rw-r--r--libs/hwui/FrameInfoVisualizer.cpp49
-rw-r--r--libs/hwui/FrameMetricsObserver.h4
-rw-r--r--libs/hwui/FrameMetricsReporter.h17
-rw-r--r--libs/hwui/GammaFontRenderer.cpp6
-rw-r--r--libs/hwui/GammaFontRenderer.h14
-rw-r--r--libs/hwui/GlFunctorLifecycleListener.h4
-rw-r--r--libs/hwui/GlLayer.cpp15
-rw-r--r--libs/hwui/GlLayer.h42
-rw-r--r--libs/hwui/Glop.h56
-rw-r--r--libs/hwui/GlopBuilder.cpp351
-rw-r--r--libs/hwui/GlopBuilder.h47
-rw-r--r--libs/hwui/GpuMemoryTracker.cpp29
-rw-r--r--libs/hwui/GpuMemoryTracker.h14
-rw-r--r--libs/hwui/GradientCache.cpp43
-rw-r--r--libs/hwui/GradientCache.h38
-rw-r--r--libs/hwui/IProfileRenderer.h2
-rw-r--r--libs/hwui/Image.cpp12
-rw-r--r--libs/hwui/Image.h16
-rw-r--r--libs/hwui/Interpolator.cpp36
-rw-r--r--libs/hwui/Interpolator.h12
-rw-r--r--libs/hwui/JankTracker.cpp140
-rw-r--r--libs/hwui/JankTracker.h4
-rw-r--r--libs/hwui/Layer.cpp46
-rw-r--r--libs/hwui/Layer.h74
-rw-r--r--libs/hwui/LayerBuilder.cpp121
-rw-r--r--libs/hwui/LayerBuilder.h64
-rw-r--r--libs/hwui/LayerUpdateQueue.cpp4
-rw-r--r--libs/hwui/LayerUpdateQueue.h15
-rw-r--r--libs/hwui/Matrix.cpp202
-rw-r--r--libs/hwui/Matrix.h60
-rw-r--r--libs/hwui/NinePatchUtils.h32
-rw-r--r--libs/hwui/OpDumper.cpp15
-rw-r--r--libs/hwui/OpDumper.h4
-rw-r--r--libs/hwui/OpenGLReadback.cpp95
-rw-r--r--libs/hwui/OpenGLReadback.h19
-rw-r--r--libs/hwui/Outline.h63
-rw-r--r--libs/hwui/Patch.cpp29
-rw-r--r--libs/hwui/Patch.h23
-rw-r--r--libs/hwui/PatchCache.cpp28
-rw-r--r--libs/hwui/PatchCache.h69
-rw-r--r--libs/hwui/PathCache.cpp61
-rw-r--r--libs/hwui/PathCache.h74
-rw-r--r--libs/hwui/PathParser.cpp153
-rw-r--r--libs/hwui/PathParser.h15
-rw-r--r--libs/hwui/PathTessellator.cpp356
-rw-r--r--libs/hwui/PathTessellator.h81
-rw-r--r--libs/hwui/PixelBuffer.cpp29
-rw-r--r--libs/hwui/PixelBuffer.h45
-rw-r--r--libs/hwui/ProfileData.cpp20
-rw-r--r--libs/hwui/ProfileData.h8
-rw-r--r--libs/hwui/ProfileDataContainer.cpp17
-rw-r--r--libs/hwui/ProfileDataContainer.h1
-rw-r--r--libs/hwui/ProfileRenderer.cpp2
-rw-r--r--libs/hwui/ProfileRenderer.h4
-rw-r--r--libs/hwui/Program.cpp6
-rw-r--r--libs/hwui/Program.h86
-rw-r--r--libs/hwui/ProgramCache.cpp260
-rw-r--r--libs/hwui/ProgramCache.h8
-rw-r--r--libs/hwui/Properties.cpp51
-rw-r--r--libs/hwui/Properties.h75
-rw-r--r--libs/hwui/PropertyValuesAnimatorSet.cpp35
-rw-r--r--libs/hwui/PropertyValuesAnimatorSet.h18
-rw-r--r--libs/hwui/PropertyValuesHolder.cpp26
-rw-r--r--libs/hwui/PropertyValuesHolder.h53
-rw-r--r--libs/hwui/Readback.h9
-rw-r--r--libs/hwui/RecordedOp.h223
-rw-r--r--libs/hwui/RecordingCanvas.cpp275
-rw-r--r--libs/hwui/RecordingCanvas.h131
-rw-r--r--libs/hwui/Rect.h125
-rw-r--r--libs/hwui/RenderBuffer.h39
-rw-r--r--libs/hwui/RenderBufferCache.cpp41
-rw-r--r--libs/hwui/RenderBufferCache.h36
-rw-r--r--libs/hwui/RenderNode.cpp111
-rw-r--r--libs/hwui/RenderNode.h150
-rw-r--r--libs/hwui/RenderProperties.cpp70
-rw-r--r--libs/hwui/RenderProperties.h284
-rw-r--r--libs/hwui/ResourceCache.cpp27
-rw-r--r--libs/hwui/ResourceCache.h14
-rw-r--r--libs/hwui/RevealClip.h13
-rw-r--r--libs/hwui/ShadowTessellator.cpp62
-rw-r--r--libs/hwui/ShadowTessellator.h28
-rw-r--r--libs/hwui/SkiaCanvas.cpp286
-rw-r--r--libs/hwui/SkiaCanvas.h116
-rw-r--r--libs/hwui/SkiaCanvasProxy.cpp199
-rw-r--r--libs/hwui/SkiaCanvasProxy.h19
-rw-r--r--libs/hwui/SkiaShader.cpp97
-rw-r--r--libs/hwui/SkiaShader.h14
-rw-r--r--libs/hwui/Snapshot.cpp25
-rw-r--r--libs/hwui/Snapshot.h24
-rw-r--r--libs/hwui/SpotShadow.cpp186
-rw-r--r--libs/hwui/SpotShadow.h42
-rw-r--r--libs/hwui/SwapBehavior.h33
-rw-r--r--libs/hwui/TessellationCache.cpp118
-rw-r--r--libs/hwui/TessellationCache.h74
-rw-r--r--libs/hwui/TextDropShadowCache.cpp24
-rw-r--r--libs/hwui/TextDropShadowCache.h58
-rw-r--r--libs/hwui/Texture.cpp218
-rw-r--r--libs/hwui/Texture.h86
-rw-r--r--libs/hwui/TextureCache.cpp40
-rw-r--r--libs/hwui/TextureCache.h14
-rw-r--r--libs/hwui/TreeInfo.h14
-rw-r--r--libs/hwui/UvMapper.h17
-rw-r--r--libs/hwui/Vector.h61
-rw-r--r--libs/hwui/VectorDrawable.cpp248
-rw-r--r--libs/hwui/VectorDrawable.h310
-rw-r--r--libs/hwui/Vertex.h38
-rw-r--r--libs/hwui/VertexBuffer.h17
-rw-r--r--libs/hwui/VkLayer.cpp4
-rw-r--r--libs/hwui/VkLayer.h30
-rw-r--r--libs/hwui/debug/DefaultGlesDriver.cpp6
-rw-r--r--libs/hwui/debug/DefaultGlesDriver.h9
-rw-r--r--libs/hwui/debug/FatalBaseDriver.cpp12
-rw-r--r--libs/hwui/debug/FatalBaseDriver.h8
-rw-r--r--libs/hwui/debug/GlesDriver.cpp6
-rw-r--r--libs/hwui/debug/GlesDriver.h8
-rw-r--r--libs/hwui/debug/GlesErrorCheckWrapper.cpp57
-rw-r--r--libs/hwui/debug/GlesErrorCheckWrapper.h8
-rw-r--r--libs/hwui/debug/MockGlesDriver.h11
-rw-r--r--libs/hwui/debug/NullGlesDriver.cpp114
-rw-r--r--libs/hwui/debug/NullGlesDriver.h163
-rw-r--r--libs/hwui/debug/ScopedReplaceDriver.h11
-rw-r--r--libs/hwui/debug/gles_decls.in3
-rw-r--r--libs/hwui/debug/gles_redefine.h3
-rw-r--r--libs/hwui/debug/gles_stubs.in5
-rw-r--r--libs/hwui/debug/nullegl.cpp55
-rw-r--r--libs/hwui/font/CacheTexture.cpp51
-rw-r--r--libs/hwui/font/CacheTexture.h80
-rw-r--r--libs/hwui/font/CachedGlyphInfo.h6
-rw-r--r--libs/hwui/font/Font.cpp159
-rw-r--r--libs/hwui/font/Font.h82
-rw-r--r--libs/hwui/font/FontCacheHistoryTracker.cpp12
-rw-r--r--libs/hwui/font/FontCacheHistoryTracker.h5
-rw-r--r--libs/hwui/font/FontUtil.h10
-rw-r--r--libs/hwui/hwui/AnimatedImageDrawable.cpp290
-rw-r--r--libs/hwui/hwui/AnimatedImageDrawable.h162
-rw-r--r--libs/hwui/hwui/AnimatedImageThread.cpp45
-rw-r--r--libs/hwui/hwui/AnimatedImageThread.h47
-rw-r--r--libs/hwui/hwui/Bitmap.cpp157
-rw-r--r--libs/hwui/hwui/Bitmap.h44
-rw-r--r--libs/hwui/hwui/Canvas.cpp80
-rw-r--r--libs/hwui/hwui/Canvas.h166
-rw-r--r--libs/hwui/hwui/MinikinSkia.cpp62
-rw-r--r--libs/hwui/hwui/MinikinSkia.h17
-rw-r--r--libs/hwui/hwui/MinikinUtils.cpp88
-rw-r--r--libs/hwui/hwui/MinikinUtils.h32
-rw-r--r--libs/hwui/hwui/Paint.h69
-rw-r--r--libs/hwui/hwui/PaintImpl.cpp61
-rw-r--r--libs/hwui/hwui/Typeface.cpp90
-rw-r--r--libs/hwui/hwui/Typeface.h28
-rw-r--r--libs/hwui/pipeline/skia/AnimatedDrawables.h34
-rw-r--r--libs/hwui/pipeline/skia/DumpOpsCanvas.h41
-rw-r--r--libs/hwui/pipeline/skia/GLFunctorDrawable.cpp188
-rw-r--r--libs/hwui/pipeline/skia/GLFunctorDrawable.h23
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.cpp90
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.h29
-rw-r--r--libs/hwui/pipeline/skia/RenderNodeDrawable.cpp129
-rw-r--r--libs/hwui/pipeline/skia/RenderNodeDrawable.h12
-rw-r--r--libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp86
-rw-r--r--libs/hwui/pipeline/skia/ReorderBarrierDrawables.h16
-rw-r--r--libs/hwui/pipeline/skia/ShaderCache.cpp144
-rw-r--r--libs/hwui/pipeline/skia/ShaderCache.h148
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.cpp51
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.h38
-rw-r--r--libs/hwui/pipeline/skia/SkiaLayer.h4
-rw-r--r--libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp175
-rw-r--r--libs/hwui/pipeline/skia/SkiaMemoryTracer.h88
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp255
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h17
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp112
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLReadback.h4
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp289
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.h64
-rw-r--r--libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp4
-rw-r--r--libs/hwui/pipeline/skia/SkiaProfileRenderer.h3
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp152
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.h85
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp65
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.h17
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanReadback.h44
-rw-r--r--libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp59
-rw-r--r--libs/hwui/pipeline/skia/VectorDrawableAtlas.h44
-rw-r--r--libs/hwui/private/hwui/DrawGlInfo.h8
-rw-r--r--libs/hwui/protos/ProtoHelpers.h6
-rw-r--r--libs/hwui/protos/graphicsstats.proto83
-rw-r--r--libs/hwui/renderstate/Blend.cpp70
-rw-r--r--libs/hwui/renderstate/Blend.h12
-rw-r--r--libs/hwui/renderstate/MeshState.cpp39
-rw-r--r--libs/hwui/renderstate/MeshState.h14
-rw-r--r--libs/hwui/renderstate/OffscreenBufferPool.cpp49
-rw-r--r--libs/hwui/renderstate/OffscreenBufferPool.h40
-rw-r--r--libs/hwui/renderstate/PixelBufferState.cpp5
-rw-r--r--libs/hwui/renderstate/PixelBufferState.h5
-rw-r--r--libs/hwui/renderstate/RenderState.cpp117
-rw-r--r--libs/hwui/renderstate/RenderState.h16
-rw-r--r--libs/hwui/renderstate/Scissor.cpp22
-rw-r--r--libs/hwui/renderstate/Scissor.h4
-rw-r--r--libs/hwui/renderstate/Stencil.cpp4
-rw-r--r--libs/hwui/renderstate/Stencil.h26
-rw-r--r--libs/hwui/renderstate/TextureState.cpp23
-rw-r--r--libs/hwui/renderstate/TextureState.h7
-rw-r--r--libs/hwui/renderthread/CacheManager.cpp115
-rw-r--r--libs/hwui/renderthread/CacheManager.h18
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp191
-rw-r--r--libs/hwui/renderthread/CanvasContext.h63
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp30
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h20
-rw-r--r--libs/hwui/renderthread/EglManager.cpp218
-rw-r--r--libs/hwui/renderthread/EglManager.h2
-rw-r--r--libs/hwui/renderthread/Frame.h7
-rw-r--r--libs/hwui/renderthread/IRenderPipeline.h35
-rw-r--r--libs/hwui/renderthread/OpenGLPipeline.cpp155
-rw-r--r--libs/hwui/renderthread/OpenGLPipeline.h27
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp625
-rw-r--r--libs/hwui/renderthread/RenderProxy.h47
-rw-r--r--libs/hwui/renderthread/RenderTask.h6
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp351
-rw-r--r--libs/hwui/renderthread/RenderThread.h69
-rw-r--r--libs/hwui/renderthread/TimeLord.cpp5
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp229
-rw-r--r--libs/hwui/renderthread/VulkanManager.h25
-rw-r--r--libs/hwui/service/GraphicsStatsService.cpp124
-rw-r--r--libs/hwui/service/GraphicsStatsService.h17
-rw-r--r--libs/hwui/tests/common/BitmapAllocationTestUtils.h44
-rw-r--r--libs/hwui/tests/common/LeakChecker.cpp18
-rw-r--r--libs/hwui/tests/common/LeakChecker.h2
-rw-r--r--libs/hwui/tests/common/TestContext.cpp48
-rw-r--r--libs/hwui/tests/common/TestContext.h17
-rw-r--r--libs/hwui/tests/common/TestListViewSceneBase.cpp27
-rw-r--r--libs/hwui/tests/common/TestListViewSceneBase.h15
-rw-r--r--libs/hwui/tests/common/TestScene.h16
-rw-r--r--libs/hwui/tests/common/TestUtils.cpp47
-rw-r--r--libs/hwui/tests/common/TestUtils.h223
-rw-r--r--libs/hwui/tests/common/scenes/BitmapFillrate.cpp25
-rw-r--r--libs/hwui/tests/common/scenes/BitmapShaders.cpp51
-rw-r--r--libs/hwui/tests/common/scenes/ClippingAnimation.cpp12
-rw-r--r--libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp23
-rw-r--r--libs/hwui/tests/common/scenes/HwBitmap565.cpp30
-rw-r--r--libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp28
-rw-r--r--libs/hwui/tests/common/scenes/HwLayerAnimation.cpp14
-rw-r--r--libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp20
-rw-r--r--libs/hwui/tests/common/scenes/JankyScene.cpp51
-rw-r--r--libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp17
-rw-r--r--libs/hwui/tests/common/scenes/ListViewAnimation.cpp27
-rw-r--r--libs/hwui/tests/common/scenes/MagnifierAnimation.cpp78
-rw-r--r--libs/hwui/tests/common/scenes/OpPropAnimation.cpp17
-rw-r--r--libs/hwui/tests/common/scenes/OvalAnimation.cpp10
-rw-r--r--libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp31
-rw-r--r--libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp12
-rw-r--r--libs/hwui/tests/common/scenes/RecentsAnimation.cpp37
-rw-r--r--libs/hwui/tests/common/scenes/RectGridAnimation.cpp17
-rw-r--r--libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp42
-rw-r--r--libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp37
-rw-r--r--libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp17
-rw-r--r--libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp25
-rw-r--r--libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp25
-rw-r--r--libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp38
-rw-r--r--libs/hwui/tests/common/scenes/ShapeAnimation.cpp128
-rw-r--r--libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp65
-rw-r--r--libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp38
-rw-r--r--libs/hwui/tests/common/scenes/TextAnimation.cpp13
-rw-r--r--libs/hwui/tests/common/scenes/TvApp.cpp182
-rw-r--r--libs/hwui/tests/macrobench/TestSceneRunner.cpp43
-rw-r--r--libs/hwui/tests/macrobench/main.cpp197
-rw-r--r--libs/hwui/tests/microbench/DisplayListCanvasBench.cpp8
-rw-r--r--libs/hwui/tests/microbench/FontBench.cpp4
-rw-r--r--libs/hwui/tests/microbench/FrameBuilderBench.cpp66
-rw-r--r--libs/hwui/tests/microbench/PathParserBench.cpp4
-rw-r--r--libs/hwui/tests/microbench/RenderNodeBench.cpp1
-rw-r--r--libs/hwui/tests/microbench/ShadowBench.cpp28
-rw-r--r--libs/hwui/tests/microbench/TaskManagerBench.cpp58
-rwxr-xr-xlibs/hwui/tests/scripts/prep_taieye.sh50
-rwxr-xr-xlibs/hwui/tests/scripts/skp-capture.sh116
-rw-r--r--libs/hwui/tests/unit/BakedOpDispatcherTests.cpp101
-rw-r--r--libs/hwui/tests/unit/BakedOpRendererTests.cpp12
-rw-r--r--libs/hwui/tests/unit/BakedOpStateTests.cpp141
-rw-r--r--libs/hwui/tests/unit/CacheManagerTests.cpp17
-rw-r--r--libs/hwui/tests/unit/CanvasContextTests.cpp4
-rw-r--r--libs/hwui/tests/unit/CanvasStateTests.cpp32
-rw-r--r--libs/hwui/tests/unit/ClipAreaTests.cpp26
-rw-r--r--libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp3
-rw-r--r--libs/hwui/tests/unit/FatVectorTests.cpp5
-rw-r--r--libs/hwui/tests/unit/FatalTestCanvas.h42
-rw-r--r--libs/hwui/tests/unit/FontRendererTests.cpp12
-rw-r--r--libs/hwui/tests/unit/FrameBuilderTests.cpp2046
-rw-r--r--libs/hwui/tests/unit/GlopBuilderTests.cpp26
-rw-r--r--libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp11
-rw-r--r--libs/hwui/tests/unit/GradientCacheTests.cpp6
-rw-r--r--libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp23
-rw-r--r--libs/hwui/tests/unit/LayerUpdateQueueTests.cpp5
-rw-r--r--libs/hwui/tests/unit/LeakCheckTests.cpp20
-rw-r--r--libs/hwui/tests/unit/LinearAllocatorTests.cpp5
-rw-r--r--libs/hwui/tests/unit/MatrixTests.cpp6
-rw-r--r--libs/hwui/tests/unit/MeshStateTests.cpp5
-rw-r--r--libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp11
-rw-r--r--libs/hwui/tests/unit/OpDumperTests.cpp2
-rw-r--r--libs/hwui/tests/unit/PathInterpolatorTests.cpp76
-rw-r--r--libs/hwui/tests/unit/RecordingCanvasTests.cpp333
-rw-r--r--libs/hwui/tests/unit/RenderNodeDrawableTests.cpp979
-rw-r--r--libs/hwui/tests/unit/RenderNodeTests.cpp87
-rw-r--r--libs/hwui/tests/unit/ShaderCacheTests.cpp176
-rw-r--r--libs/hwui/tests/unit/SkiaBehaviorTests.cpp16
-rw-r--r--libs/hwui/tests/unit/SkiaCanvasTests.cpp31
-rw-r--r--libs/hwui/tests/unit/SkiaDisplayListTests.cpp34
-rw-r--r--libs/hwui/tests/unit/SkiaPipelineTests.cpp270
-rw-r--r--libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp137
-rw-r--r--libs/hwui/tests/unit/SnapshotTests.cpp8
-rw-r--r--libs/hwui/tests/unit/StringUtilsTests.cpp2
-rw-r--r--libs/hwui/tests/unit/TestUtilsTests.cpp2
-rw-r--r--libs/hwui/tests/unit/TextDropShadowCacheTests.cpp9
-rw-r--r--libs/hwui/tests/unit/ThreadBaseTests.cpp151
-rw-r--r--libs/hwui/tests/unit/TypefaceTests.cpp457
-rw-r--r--libs/hwui/tests/unit/VectorDrawableAtlasTests.cpp59
-rw-r--r--libs/hwui/tests/unit/VectorDrawableTests.cpp436
-rw-r--r--libs/hwui/tests/unit/main.cpp18
-rw-r--r--libs/hwui/thread/Barrier.h11
-rw-r--r--libs/hwui/thread/Future.h15
-rw-r--r--libs/hwui/thread/Signal.h11
-rw-r--r--libs/hwui/thread/Task.h32
-rw-r--r--libs/hwui/thread/TaskManager.cpp6
-rw-r--r--libs/hwui/thread/TaskManager.h19
-rw-r--r--libs/hwui/thread/TaskProcessor.h24
-rw-r--r--libs/hwui/thread/ThreadBase.h85
-rw-r--r--libs/hwui/thread/WorkQueue.h145
-rw-r--r--libs/hwui/utils/Blur.cpp59
-rw-r--r--libs/hwui/utils/Blur.h16
-rw-r--r--libs/hwui/utils/Color.cpp73
-rw-r--r--libs/hwui/utils/Color.h171
-rw-r--r--libs/hwui/utils/FatVector.h34
-rw-r--r--libs/hwui/utils/GLUtils.cpp32
-rw-r--r--libs/hwui/utils/GLUtils.h15
-rw-r--r--libs/hwui/utils/LinearAllocator.cpp52
-rw-r--r--libs/hwui/utils/LinearAllocator.h42
-rw-r--r--libs/hwui/utils/Macros.h22
-rw-r--r--libs/hwui/utils/MathUtils.h24
-rw-r--r--libs/hwui/utils/PaintUtils.h17
-rw-r--r--libs/hwui/utils/Pair.h40
-rw-r--r--libs/hwui/utils/RingBuffer.h22
-rw-r--r--libs/hwui/utils/StringUtils.cpp4
-rw-r--r--libs/hwui/utils/StringUtils.h13
-rw-r--r--libs/hwui/utils/TestWindowContext.cpp70
-rw-r--r--libs/hwui/utils/TestWindowContext.h4
-rw-r--r--libs/hwui/utils/TimeUtils.h6
-rw-r--r--libs/hwui/utils/Timing.h10
-rw-r--r--libs/hwui/utils/TraceUtils.h10
-rw-r--r--libs/hwui/utils/VectorDrawableUtils.cpp610
-rw-r--r--libs/hwui/utils/VectorDrawableUtils.h10
389 files changed, 14529 insertions, 12840 deletions
diff --git a/libs/hwui/.clang-format b/libs/hwui/.clang-format
new file mode 100644
index 000000000000..5e9bba8377cb
--- /dev/null
+++ b/libs/hwui/.clang-format
@@ -0,0 +1,10 @@
+BasedOnStyle: Google
+DerivePointerAlignment: false
+IndentWidth: 4
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+ColumnLimit: 100
+AllowShortFunctionsOnASingleLine: Inline
+AccessModifierOffset: -4
+#BreakConstructorInitializers: BeforeComma
+BreakConstructorInitializersBeforeComma: true
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 3982fa0938bf..aa96698c1e53 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -25,7 +25,7 @@
// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
// therefore, the maximum number of extra vertices will be twice bigger.
-#define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI)
+#define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI)
// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI)
@@ -36,9 +36,9 @@
*/
#define EXTRA_EDGE_VERTEX_PER_PI 50
-#define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI)
+#define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI)
-#define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI)
+#define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI)
/**
* Other constants:
@@ -56,8 +56,8 @@
#include "Vertex.h"
#include "VertexBuffer.h"
-#include <algorithm>
#include <utils/Log.h>
+#include <algorithm>
namespace android {
namespace uirenderer {
@@ -67,8 +67,8 @@ namespace uirenderer {
*/
inline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) {
// Convert from Vector3 to Vector2 first.
- Vector2 currentVertex = { vertices[current].x, vertices[current].y };
- Vector2 nextVertex = { vertices[next].x, vertices[next].y };
+ Vector2 currentVertex = {vertices[current].x, vertices[current].y};
+ Vector2 nextVertex = {vertices[next].x, vertices[next].y};
return ShadowTessellator::calculateNormal(currentVertex, nextVertex);
}
@@ -79,24 +79,24 @@ inline float getAlphaFromFactoredZ(float factoredZ) {
return 1.0 / (1 + std::max(factoredZ, 0.0f));
}
-inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike,
- const Vector3& secondVertex, const Vector3& centroid) {
- Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
+inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike, const Vector3& secondVertex,
+ const Vector3& centroid) {
+ Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
secondSpike.normalize();
int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike,
- EDGE_RADIANS_DIVISOR);
+ EDGE_RADIANS_DIVISOR);
*currentSpike = secondSpike;
return result;
}
// Given the caster's vertex count, compute all the buffers size depending on
// whether or not the caster is opaque.
-inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount,
- int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) {
+inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount, int* totalUmbraCount,
+ int casterVertexCount, bool isCasterOpaque) {
// Compute the size of the vertex buffer.
- int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER +
- MAX_EXTRA_EDGE_VERTEX_NUMBER;
+ int outerVertexCount =
+ casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER + MAX_EXTRA_EDGE_VERTEX_NUMBER;
int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER;
*totalVertexCount = outerVertexCount + innerVertexCount;
@@ -163,44 +163,42 @@ inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) {
* | |
* (V3)-----------------------------------(V2)
*/
-void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
- const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d,
- float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
+void AmbientShadow::createAmbientShadow(bool isCasterOpaque, const Vector3* casterVertices,
+ int casterVertexCount, const Vector3& centroid3d,
+ float heightFactor, float geomFactor,
+ VertexBuffer& shadowVertexBuffer) {
shadowVertexBuffer.setMeshFeatureFlags(VertexBuffer::kAlpha | VertexBuffer::kIndices);
// In order to computer the outer vertices in one loop, we need pre-compute
// the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value
// for vertex 0.
- Vector2 previousNormal = getNormalFromVertices(casterVertices,
- casterVertexCount - 1 , 0);
- Vector2 currentSpike = {casterVertices[0].x - centroid3d.x,
- casterVertices[0].y - centroid3d.y};
+ Vector2 previousNormal = getNormalFromVertices(casterVertices, casterVertexCount - 1, 0);
+ Vector2 currentSpike = {casterVertices[0].x - centroid3d.x, casterVertices[0].y - centroid3d.y};
currentSpike.normalize();
float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor);
// Preparing all the output data.
int totalVertexCount, totalIndexCount, totalUmbraCount;
- computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount,
- casterVertexCount, isCasterOpaque);
- AlphaVertex* shadowVertices =
- shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount);
+ computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount, casterVertexCount,
+ isCasterOpaque);
+ AlphaVertex* shadowVertices = shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount);
int vertexBufferIndex = 0;
uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount);
int indexBufferIndex = 0;
uint16_t umbraVertices[totalUmbraCount];
int umbraIndex = 0;
- for (int i = 0; i < casterVertexCount; i++) {
+ for (int i = 0; i < casterVertexCount; i++) {
// Corner: first figure out the extra vertices we need for the corner.
const Vector3& innerVertex = casterVertices[i];
- Vector2 currentNormal = getNormalFromVertices(casterVertices, i,
- (i + 1) % casterVertexCount);
+ Vector2 currentNormal =
+ getNormalFromVertices(casterVertices, i, (i + 1) % casterVertexCount);
- int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber(currentNormal,
- previousNormal, CORNER_RADIANS_DIVISOR);
+ int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber(
+ currentNormal, previousNormal, CORNER_RADIANS_DIVISOR);
float expansionDist = innerVertex.z * heightFactor * geomFactor;
- const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
+ const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
#if DEBUG_SHADOW
ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber);
#endif
@@ -212,9 +210,8 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
if (!isCasterOpaque) {
umbraVertices[umbraIndex++] = vertexBufferIndex;
}
- AlphaVertex::set(&shadowVertices[vertexBufferIndex++],
- casterVertices[i].x, casterVertices[i].y,
- currentAlpha);
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x,
+ casterVertices[i].y, currentAlpha);
const Vector3& innerStart = casterVertices[i];
@@ -225,8 +222,7 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
// This will create vertices from [0, cornerSlicesNumber] inclusively,
// which means minimally 2 vertices even without the extra ones.
for (int j = 0; j <= cornerSlicesNumber; j++) {
- Vector2 averageNormal =
- previousNormal * (cornerSlicesNumber - j) + currentNormal * j;
+ Vector2 averageNormal = previousNormal * (cornerSlicesNumber - j) + currentNormal * j;
averageNormal /= cornerSlicesNumber;
averageNormal.normalize();
Vector2 outerVertex;
@@ -235,8 +231,8 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
indexBuffer[indexBufferIndex++] = vertexBufferIndex;
indexBuffer[indexBufferIndex++] = currentInnerVertexIndex;
- AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x,
- outerVertex.y, OUTER_ALPHA);
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x, outerVertex.y,
+ OUTER_ALPHA);
if (j == 0) {
outerStart = outerVertex;
@@ -257,8 +253,8 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
outerNext.y = innerNext.y + currentNormal.y * expansionDist;
// Compute the angle and see how many extra points we need.
- int extraVerticesNumber = getEdgeExtraAndUpdateSpike(&currentSpike,
- innerNext, centroid3d);
+ int extraVerticesNumber =
+ getEdgeExtraAndUpdateSpike(&currentSpike, innerNext, centroid3d);
#if DEBUG_SHADOW
ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i);
#endif
@@ -269,20 +265,20 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
for (int k = 1; k < extraVerticesNumber; k++) {
int startWeight = extraVerticesNumber - k;
Vector2 currentOuter =
- (outerLast * startWeight + outerNext * k) / extraVerticesNumber;
+ (outerLast * startWeight + outerNext * k) / extraVerticesNumber;
indexBuffer[indexBufferIndex++] = vertexBufferIndex;
AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x,
- currentOuter.y, OUTER_ALPHA);
+ currentOuter.y, OUTER_ALPHA);
if (!isCasterOpaque) {
umbraVertices[umbraIndex++] = vertexBufferIndex;
}
Vector3 currentInner =
- (innerStart * startWeight + innerNext * k) / extraVerticesNumber;
+ (innerStart * startWeight + innerNext * k) / extraVerticesNumber;
indexBuffer[indexBufferIndex++] = vertexBufferIndex;
AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x,
- currentInner.y,
- getAlphaFromFactoredZ(currentInner.z * heightFactor));
+ currentInner.y,
+ getAlphaFromFactoredZ(currentInner.z * heightFactor));
}
}
currentAlpha = nextAlpha;
@@ -293,11 +289,10 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
if (!isCasterOpaque) {
// Add the centroid as the last one in the vertex buffer.
- float centroidOpacity =
- getAlphaFromFactoredZ(centroid3d.z * heightFactor);
+ float centroidOpacity = getAlphaFromFactoredZ(centroid3d.z * heightFactor);
int centroidIndex = vertexBufferIndex;
- AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x,
- centroid3d.y, centroidOpacity);
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x, centroid3d.y,
+ centroidOpacity);
for (int i = 0; i < umbraIndex; i++) {
// Note that umbraVertices[0] is always 0.
@@ -322,7 +317,7 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
#if DEBUG_SHADOW
for (int i = 0; i < vertexBufferIndex; i++) {
ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y,
- shadowVertices[i].alpha);
+ shadowVertices[i].alpha);
}
for (int i = 0; i < indexBufferIndex; i++) {
ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]);
@@ -330,5 +325,5 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
#endif
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/AmbientShadow.h b/libs/hwui/AmbientShadow.h
index 8eb1048f4d1c..cb1d915f2540 100644
--- a/libs/hwui/AmbientShadow.h
+++ b/libs/hwui/AmbientShadow.h
@@ -31,12 +31,12 @@ class VertexBuffer;
*/
class AmbientShadow {
public:
- static void createAmbientShadow(bool isCasterOpaque, const Vector3* poly,
- int polyLength, const Vector3& centroid3d, float heightFactor,
- float geomFactor, VertexBuffer& shadowVertexBuffer);
-}; // AmbientShadow
+ static void createAmbientShadow(bool isCasterOpaque, const Vector3* poly, int polyLength,
+ const Vector3& centroid3d, float heightFactor, float geomFactor,
+ VertexBuffer& shadowVertexBuffer);
+}; // AmbientShadow
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_AMBIENT_SHADOW_H
+#endif // ANDROID_HWUI_AMBIENT_SHADOW_H
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index c468038d61c2..fb8274426b16 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -2,11 +2,15 @@ cc_defaults {
name: "hwui_defaults",
defaults: [
"hwui_static_deps",
-
+ "skia_deps",
//"hwui_bugreport_font_cache_usage",
//"hwui_compile_for_perf",
+ "hwui_pgo",
+ "hwui_lto",
],
+ cpp_std: "c++17",
+
cflags: [
"-DEGL_EGLEXT_PROTOTYPES",
"-DGL_GLEXT_PROTOTYPES",
@@ -37,6 +41,7 @@ cc_defaults {
"external/skia/src/image",
"external/skia/src/utils",
"external/skia/src/gpu",
+ "external/skia/src/shaders",
],
product_variables: {
@@ -60,7 +65,6 @@ cc_defaults {
"libEGL",
"libGLESv2",
"libvulkan",
- "libskia",
"libui",
"libgui",
"libprotobuf-cpp-lite",
@@ -71,7 +75,7 @@ cc_defaults {
"libRScpp",
],
static_libs: [
- "libplatformprotos",
+ "libEGL_blobCache",
],
}
@@ -112,6 +116,34 @@ cc_defaults {
include_dirs: ["frameworks/native/opengl/libs/GLES2"],
}
+// Build libhwui with PGO by default.
+// Location of PGO profile data is defined in build/soong/cc/pgo.go
+// and is separate from hwui.
+// To turn it off, set ANDROID_PGO_NO_PROFILE_USE environment variable
+// or set enable_profile_use property to false.
+cc_defaults {
+ name: "hwui_pgo",
+
+ pgo: {
+ instrumentation: true,
+ profile_file: "hwui/hwui.profdata",
+ benchmarks: ["hwui"],
+ enable_profile_use: true,
+ },
+}
+
+// Build hwui library with ThinLTO by default.
+cc_defaults {
+ name: "hwui_lto",
+ target: {
+ android: {
+ lto: {
+ thin: true,
+ },
+ },
+ },
+}
+
// ------------------------
// library
// ------------------------
@@ -119,7 +151,12 @@ cc_defaults {
cc_defaults {
name: "libhwui_defaults",
defaults: ["hwui_defaults"],
+
+ whole_static_libs: ["libskia"],
+
srcs: [
+ "hwui/AnimatedImageDrawable.cpp",
+ "hwui/AnimatedImageThread.cpp",
"hwui/Bitmap.cpp",
"font/CacheTexture.cpp",
"font/Font.cpp",
@@ -132,7 +169,9 @@ cc_defaults {
"pipeline/skia/LayerDrawable.cpp",
"pipeline/skia/RenderNodeDrawable.cpp",
"pipeline/skia/ReorderBarrierDrawables.cpp",
+ "pipeline/skia/ShaderCache.cpp",
"pipeline/skia/SkiaDisplayList.cpp",
+ "pipeline/skia/SkiaMemoryTracer.cpp",
"pipeline/skia/SkiaOpenGLPipeline.cpp",
"pipeline/skia/SkiaOpenGLReadback.cpp",
"pipeline/skia/SkiaPipeline.cpp",
@@ -233,6 +272,7 @@ cc_defaults {
"TextureCache.cpp",
"VectorDrawable.cpp",
"VkLayer.cpp",
+ "protos/graphicsstats.proto",
"protos/hwui.proto",
],
@@ -253,7 +293,7 @@ cc_library {
// If enabled, every GLES call is wrapped & error checked
// Has moderate overhead
"hwui_enable_opengl_validation",
-],
+ ],
}
// ------------------------
@@ -298,7 +338,9 @@ cc_test {
"libgmock",
"libhwui_static_debug",
],
- shared_libs: ["libmemunreachable"],
+ shared_libs: [
+ "libmemunreachable",
+ ],
cflags: [
"-include debug/wrap_gles.h",
"-DHWUI_NULL_GPU",
@@ -335,6 +377,7 @@ cc_test {
"tests/unit/RecordingCanvasTests.cpp",
"tests/unit/RenderNodeTests.cpp",
"tests/unit/RenderPropertiesTests.cpp",
+ "tests/unit/ShaderCacheTests.cpp",
"tests/unit/SkiaBehaviorTests.cpp",
"tests/unit/SkiaDisplayListTests.cpp",
"tests/unit/SkiaPipelineTests.cpp",
@@ -345,7 +388,8 @@ cc_test {
"tests/unit/TestUtilsTests.cpp",
"tests/unit/TextDropShadowCacheTests.cpp",
"tests/unit/TextureCacheTests.cpp",
- "tests/unit/TypefaceTests.cpp",
+ "tests/unit/ThreadBaseTests.cpp",
+ "tests/unit/TypefaceTests.cpp",
"tests/unit/VectorDrawableTests.cpp",
"tests/unit/VectorDrawableAtlasTests.cpp",
],
@@ -361,7 +405,9 @@ cc_benchmark {
// set to libhwui_static_debug to skip actual GL commands
whole_static_libs: ["libhwui"],
- shared_libs: ["libmemunreachable"],
+ shared_libs: [
+ "libmemunreachable",
+ ],
srcs: [
"tests/macrobench/TestSceneRunner.cpp",
@@ -383,7 +429,9 @@ cc_benchmark {
],
whole_static_libs: ["libhwui_static_debug"],
- shared_libs: ["libmemunreachable"],
+ shared_libs: [
+ "libmemunreachable",
+ ],
srcs: [
"tests/microbench/main.cpp",
@@ -397,3 +445,15 @@ cc_benchmark {
"tests/microbench/TaskManagerBench.cpp",
],
}
+
+// ----------------------------------------
+// Phony target to build benchmarks for PGO
+// ----------------------------------------
+
+phony {
+ name: "pgo-targets-hwui",
+ required: [
+ "hwuimicro",
+ "hwuimacro",
+ ]
+}
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
index 5759ccd85464..46c9da2ac6b8 100644
--- a/libs/hwui/AnimationContext.cpp
+++ b/libs/hwui/AnimationContext.cpp
@@ -26,11 +26,9 @@ AnimationContext::AnimationContext(renderthread::TimeLord& clock)
: mClock(clock)
, mCurrentFrameAnimations(*this)
, mNextFrameAnimations(*this)
- , mFrameTimeMs(0) {
-}
+ , mFrameTimeMs(0) {}
-AnimationContext::~AnimationContext() {
-}
+AnimationContext::~AnimationContext() {}
void AnimationContext::destroy() {
startFrame(TreeInfo::MODE_RT_ONLY);
@@ -39,7 +37,7 @@ void AnimationContext::destroy() {
AnimatorManager& animators = current->mRenderNode->animators();
animators.endAllActiveAnimators();
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
- "endAllAnimators failed to remove from current frame list!");
+ "endAllAnimators failed to remove from current frame list!");
}
}
@@ -56,7 +54,7 @@ void AnimationContext::addAnimationHandle(AnimationHandle* handle) {
void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
- "Missed running animations last frame!");
+ "Missed running animations last frame!");
AnimationHandle* head = mNextFrameAnimations.mNextHandle;
if (head) {
mNextFrameAnimations.mNextHandle = nullptr;
@@ -73,20 +71,17 @@ void AnimationContext::runRemainingAnimations(TreeInfo& info) {
animators.pushStaging();
animators.animateNoDamage(info);
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
- "Animate failed to remove from current frame list!");
+ "Animate failed to remove from current frame list!");
}
}
void AnimationContext::callOnFinished(BaseRenderNodeAnimator* animator,
- AnimationListener* listener) {
+ AnimationListener* listener) {
listener->onAnimationFinished(animator);
}
AnimationHandle::AnimationHandle(AnimationContext& context)
- : mContext(context)
- , mPreviousHandle(nullptr)
- , mNextHandle(nullptr) {
-}
+ : mContext(context), mPreviousHandle(nullptr), mNextHandle(nullptr) {}
AnimationHandle::AnimationHandle(RenderNode& animatingNode, AnimationContext& context)
: mRenderNode(&animatingNode)
@@ -98,7 +93,7 @@ AnimationHandle::AnimationHandle(RenderNode& animatingNode, AnimationContext& co
AnimationHandle::~AnimationHandle() {
LOG_ALWAYS_FATAL_IF(mPreviousHandle || mNextHandle,
- "AnimationHandle destroyed while still animating!");
+ "AnimationHandle destroyed while still animating!");
}
void AnimationHandle::notifyAnimationsRan() {
@@ -112,7 +107,7 @@ void AnimationHandle::notifyAnimationsRan() {
void AnimationHandle::release() {
LOG_ALWAYS_FATAL_IF(mRenderNode->animators().hasAnimators(),
- "Releasing the handle for an RenderNode with outstanding animators!");
+ "Releasing the handle for an RenderNode with outstanding animators!");
removeFromList();
mRenderNode->animators().setAnimationHandle(nullptr);
delete this;
diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h
index 71ee8602a29f..74d5e79c0b77 100644
--- a/libs/hwui/AnimationContext.h
+++ b/libs/hwui/AnimationContext.h
@@ -43,6 +43,7 @@ class RenderNode;
*/
class AnimationHandle {
PREVENT_COPY_AND_ASSIGN(AnimationHandle);
+
public:
AnimationContext& context() { return mContext; }
@@ -74,14 +75,14 @@ private:
class AnimationContext {
PREVENT_COPY_AND_ASSIGN(AnimationContext);
+
public:
ANDROID_API explicit AnimationContext(renderthread::TimeLord& clock);
ANDROID_API virtual ~AnimationContext();
nsecs_t frameTimeMs() { return mFrameTimeMs; }
bool hasAnimations() {
- return mCurrentFrameAnimations.mNextHandle
- || mNextFrameAnimations.mNextHandle;
+ return mCurrentFrameAnimations.mNextHandle || mNextFrameAnimations.mNextHandle;
}
// Will always add to the next frame list, which is swapped when
@@ -96,7 +97,8 @@ public:
// as part of the standard RenderNode:prepareTree pass.
ANDROID_API virtual void runRemainingAnimations(TreeInfo& info);
- ANDROID_API virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener);
+ ANDROID_API virtual void callOnFinished(BaseRenderNodeAnimator* animator,
+ AnimationListener* listener);
ANDROID_API virtual void destroy();
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index b6fbf891f84d..74cf1fda1b75 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -44,16 +44,14 @@ BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
, mDuration(300)
, mStartDelay(0)
, mMayRunAsync(true)
- , mPlayTime(0) {
-}
+ , mPlayTime(0) {}
-BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
-}
+BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {}
void BaseRenderNodeAnimator::checkMutable() {
// Should be impossible to hit as the Java-side also has guards for this
LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
- "Animator has already been started!");
+ "Animator has already been started!");
}
void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
@@ -119,34 +117,36 @@ void BaseRenderNodeAnimator::end() {
void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
switch (request) {
- case Request::Start:
- mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
- mPlayTime : 0;
- mPlayState = PlayState::Running;
- mPendingActionUponFinish = Action::None;
- break;
- case Request::Reverse:
- mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
- mPlayTime : mDuration;
- mPlayState = PlayState::Reversing;
- mPendingActionUponFinish = Action::None;
- break;
- case Request::Reset:
- mPlayTime = 0;
- mPlayState = PlayState::Finished;
- mPendingActionUponFinish = Action::Reset;
- break;
- case Request::Cancel:
- mPlayState = PlayState::Finished;
- mPendingActionUponFinish = Action::None;
- break;
- case Request::End:
- mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
- mPlayState = PlayState::Finished;
- mPendingActionUponFinish = Action::End;
- break;
- default:
- LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
+ case Request::Start:
+ mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing)
+ ? mPlayTime
+ : 0;
+ mPlayState = PlayState::Running;
+ mPendingActionUponFinish = Action::None;
+ break;
+ case Request::Reverse:
+ mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing)
+ ? mPlayTime
+ : mDuration;
+ mPlayState = PlayState::Reversing;
+ mPendingActionUponFinish = Action::None;
+ break;
+ case Request::Reset:
+ mPlayTime = 0;
+ mPlayState = PlayState::Finished;
+ mPendingActionUponFinish = Action::Reset;
+ break;
+ case Request::Cancel:
+ mPlayState = PlayState::Finished;
+ mPendingActionUponFinish = Action::None;
+ break;
+ case Request::End:
+ mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
+ mPlayState = PlayState::Finished;
+ mPendingActionUponFinish = Action::End;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
};
}
@@ -182,8 +182,8 @@ void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
if (mStagingPlayState == PlayState::Finished) {
callOnFinishedListener(context);
- } else if (mStagingPlayState == PlayState::Running
- || mStagingPlayState == PlayState::Reversing) {
+ } else if (mStagingPlayState == PlayState::Running ||
+ mStagingPlayState == PlayState::Reversing) {
bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
if (prevFramePlayState != mStagingPlayState) {
transitionToRunning(context);
@@ -197,7 +197,7 @@ void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
if (mPlayState == PlayState::Reversing) {
// Reverse is not supported for animations with a start delay, so here we
// assume no start delay.
- mStartTime = currentFrameTime - (mDuration - mPlayTime);
+ mStartTime = currentFrameTime - (mDuration - mPlayTime);
} else {
// Animation should play forward
if (mPlayTime == 0) {
@@ -223,9 +223,9 @@ void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
}
mStartTime = frameTimeMs + mStartDelay;
if (mStartTime < 0) {
- ALOGW("Ended up with a really weird start time of %" PRId64
- " with frame time %" PRId64 " and start delay %" PRId64,
- mStartTime, frameTimeMs, mStartDelay);
+ ALOGW("Ended up with a really weird start time of %" PRId64 " with frame time %" PRId64
+ " and start delay %" PRId64,
+ mStartTime, frameTimeMs, mStartDelay);
// Set to 0 so that the animate() basically instantly finishes
mStartTime = 0;
}
@@ -247,7 +247,7 @@ bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
updatePlayTime(mDuration);
}
// Reset pending action.
- mPendingActionUponFinish = Action ::None;
+ mPendingActionUponFinish = Action::None;
return true;
}
@@ -276,7 +276,7 @@ bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
float fraction = 1.0f;
if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
- fraction = mPlayTime / (float) mDuration;
+ fraction = mPlayTime / (float)mDuration;
}
fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
@@ -308,35 +308,35 @@ void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
************************************************************/
struct RenderPropertyAnimator::PropertyAccessors {
- RenderNode::DirtyPropertyMask dirtyMask;
- GetFloatProperty getter;
- SetFloatProperty setter;
+ RenderNode::DirtyPropertyMask dirtyMask;
+ GetFloatProperty getter;
+ SetFloatProperty setter;
};
// Maps RenderProperty enum to accessors
const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
- {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
- {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
- {RenderNode::TRANSLATION_Z, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
- {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
- {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
- {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
- {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
- {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
- {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
- {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
- {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
- {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
+ {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX,
+ &RenderProperties::setTranslationX},
+ {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY,
+ &RenderProperties::setTranslationY},
+ {RenderNode::TRANSLATION_Z, &RenderProperties::getTranslationZ,
+ &RenderProperties::setTranslationZ},
+ {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX},
+ {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY},
+ {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation},
+ {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX},
+ {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY},
+ {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX},
+ {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY},
+ {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ},
+ {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha},
};
RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
- : BaseRenderNodeAnimator(finalValue)
- , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
-}
+ : BaseRenderNodeAnimator(finalValue), mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {}
void RenderPropertyAnimator::onAttached() {
- if (!mHasStartValue
- && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
+ if (!mHasStartValue && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)());
}
}
@@ -385,11 +385,9 @@ void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
* CanvasPropertyPrimitiveAnimator
************************************************************/
-CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
- CanvasPropertyPrimitive* property, float finalValue)
- : BaseRenderNodeAnimator(finalValue)
- , mProperty(property) {
-}
+CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
+ float finalValue)
+ : BaseRenderNodeAnimator(finalValue), mProperty(property) {}
float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
return mProperty->value;
@@ -407,50 +405,44 @@ uint32_t CanvasPropertyPrimitiveAnimator::dirtyMask() {
* CanvasPropertySkPaintAnimator
************************************************************/
-CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
- CanvasPropertyPaint* property, PaintField field, float finalValue)
- : BaseRenderNodeAnimator(finalValue)
- , mProperty(property)
- , mField(field) {
-}
+CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
+ PaintField field, float finalValue)
+ : BaseRenderNodeAnimator(finalValue), mProperty(property), mField(field) {}
float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
switch (mField) {
- case STROKE_WIDTH:
- return mProperty->value.getStrokeWidth();
- case ALPHA:
- return mProperty->value.getAlpha();
+ case STROKE_WIDTH:
+ return mProperty->value.getStrokeWidth();
+ case ALPHA:
+ return mProperty->value.getAlpha();
}
- LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
+ LOG_ALWAYS_FATAL("Unknown field %d", (int)mField);
return -1;
}
static uint8_t to_uint8(float value) {
- int c = (int) (value + .5f);
- return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
+ int c = (int)(value + .5f);
+ return static_cast<uint8_t>(c < 0 ? 0 : c > 255 ? 255 : c);
}
void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
switch (mField) {
- case STROKE_WIDTH:
- mProperty->value.setStrokeWidth(value);
- return;
- case ALPHA:
- mProperty->value.setAlpha(to_uint8(value));
- return;
+ case STROKE_WIDTH:
+ mProperty->value.setStrokeWidth(value);
+ return;
+ case ALPHA:
+ mProperty->value.setAlpha(to_uint8(value));
+ return;
}
- LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
+ LOG_ALWAYS_FATAL("Unknown field %d", (int)mField);
}
uint32_t CanvasPropertyPaintAnimator::dirtyMask() {
return RenderNode::DISPLAY_LIST;
}
-RevealAnimator::RevealAnimator(int centerX, int centerY,
- float startValue, float finalValue)
- : BaseRenderNodeAnimator(finalValue)
- , mCenterX(centerX)
- , mCenterY(centerY) {
+RevealAnimator::RevealAnimator(int centerX, int centerY, float startValue, float finalValue)
+ : BaseRenderNodeAnimator(finalValue), mCenterX(centerX), mCenterY(centerY) {
setStartValue(startValue);
}
@@ -459,8 +451,7 @@ float RevealAnimator::getValue(RenderNode* target) const {
}
void RevealAnimator::setValue(RenderNode* target, float value) {
- target->animatorProperties().mutableRevealClip().set(true,
- mCenterX, mCenterY, value);
+ target->animatorProperties().mutableRevealClip().set(true, mCenterX, mCenterY, value);
}
uint32_t RevealAnimator::dirtyMask() {
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index aac355c11ac9..42f4cf8828bd 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -16,11 +16,11 @@
#ifndef ANIMATOR_H
#define ANIMATOR_H
-#include <memory>
#include <cutils/compiler.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
+#include <memory>
#include "utils/Macros.h"
@@ -40,6 +40,7 @@ class RenderProperties;
class AnimationListener : public VirtualLightRefBase {
public:
ANDROID_API virtual void onAnimationFinished(BaseRenderNodeAnimator*) = 0;
+
protected:
ANDROID_API virtual ~AnimationListener() {}
};
@@ -52,6 +53,7 @@ enum class RepeatMode {
class BaseRenderNodeAnimator : public VirtualLightRefBase {
PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
+
public:
ANDROID_API void setStartValue(float value);
ANDROID_API void setInterpolator(Interpolator* interpolator);
@@ -59,13 +61,9 @@ public:
ANDROID_API nsecs_t duration() { return mDuration; }
ANDROID_API void setStartDelay(nsecs_t startDelayInMs);
ANDROID_API nsecs_t startDelay() { return mStartDelay; }
- ANDROID_API void setListener(AnimationListener* listener) {
- mListener = listener;
- }
+ ANDROID_API void setListener(AnimationListener* listener) { mListener = listener; }
AnimationListener* listener() { return mListener.get(); }
- ANDROID_API void setAllowRunningAsync(bool mayRunAsync) {
- mMayRunAsync = mayRunAsync;
- }
+ ANDROID_API void setAllowRunningAsync(bool mayRunAsync) { mMayRunAsync = mayRunAsync; }
bool mayRunAsync() { return mMayRunAsync; }
ANDROID_API void start();
ANDROID_API virtual void reset();
@@ -86,8 +84,9 @@ public:
// an animation on RenderThread.
ANDROID_API nsecs_t getRemainingPlayTime();
- bool isRunning() { return mPlayState == PlayState::Running
- || mPlayState == PlayState::Reversing; }
+ bool isRunning() {
+ return mPlayState == PlayState::Running || mPlayState == PlayState::Reversing;
+ }
bool isFinished() { return mPlayState == PlayState::Finished; }
float finalValue() { return mFinalValue; }
@@ -158,13 +157,7 @@ protected:
sp<AnimationListener> mListener;
private:
- enum class Request {
- Start,
- Reverse,
- Reset,
- Cancel,
- End
- };
+ enum class Request { Start, Reverse, Reset, Cancel, End };
// Defines different actions upon finish.
enum class Action {
@@ -229,13 +222,14 @@ private:
class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
public:
ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
- float finalValue);
+ float finalValue);
ANDROID_API virtual uint32_t dirtyMask();
protected:
virtual float getValue(RenderNode* target) const override;
virtual void setValue(RenderNode* target, float value) override;
+
private:
sp<CanvasPropertyPrimitive> mProperty;
};
@@ -247,14 +241,15 @@ public:
ALPHA,
};
- ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
- PaintField field, float finalValue);
+ ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property, PaintField field,
+ float finalValue);
ANDROID_API virtual uint32_t dirtyMask();
protected:
virtual float getValue(RenderNode* target) const override;
virtual void setValue(RenderNode* target, float value) override;
+
private:
sp<CanvasPropertyPaint> mProperty;
PaintField mField;
@@ -262,8 +257,7 @@ private:
class RevealAnimator : public BaseRenderNodeAnimator {
public:
- ANDROID_API RevealAnimator(int centerX, int centerY,
- float startValue, float finalValue);
+ ANDROID_API RevealAnimator(int centerX, int centerY, float startValue, float finalValue);
ANDROID_API virtual uint32_t dirtyMask();
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 69ead5890566..4826d5a0c8da 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -17,8 +17,8 @@
#include <algorithm>
-#include "Animator.h"
#include "AnimationContext.h"
+#include "Animator.h"
#include "DamageAccumulator.h"
#include "RenderNode.h"
@@ -31,10 +31,7 @@ static void detach(sp<BaseRenderNodeAnimator>& animator) {
animator->detach();
}
-AnimatorManager::AnimatorManager(RenderNode& parent)
- : mParent(parent)
- , mAnimationHandle(nullptr) {
-}
+AnimatorManager::AnimatorManager(RenderNode& parent) : mParent(parent), mAnimationHandle(nullptr) {}
AnimatorManager::~AnimatorManager() {
for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
@@ -58,22 +55,22 @@ void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
- mNewAnimators.end());
+ mNewAnimators.end());
}
void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
mAnimationHandle = handle;
LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
- "Lost animation handle on %p (%s) with outstanding animators!",
- &mParent, mParent.getName());
+ "Lost animation handle on %p (%s) with outstanding animators!", &mParent,
+ mParent.getName());
}
void AnimatorManager::pushStaging() {
if (mNewAnimators.size()) {
if (CC_UNLIKELY(!mAnimationHandle)) {
- ALOGW("Trying to start new animators on %p (%s) without an animation handle!",
- &mParent, mParent.getName());
+ ALOGW("Trying to start new animators on %p (%s) without an animation handle!", &mParent,
+ mParent.getName());
return;
}
@@ -100,7 +97,7 @@ public:
AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
: mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
- bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+ bool operator()(sp<BaseRenderNodeAnimator>& animator) {
*mDirtyMask |= animator->dirtyMask();
bool remove = animator->animate(mContext);
if (remove) {
@@ -172,17 +169,15 @@ class EndActiveAnimatorsFunctor {
public:
explicit EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
- void operator() (sp<BaseRenderNodeAnimator>& animator) {
- animator->forceEndNow(mContext);
- }
+ void operator()(sp<BaseRenderNodeAnimator>& animator) { animator->forceEndNow(mContext); }
private:
AnimationContext& mContext;
};
void AnimatorManager::endAllActiveAnimators() {
- ALOGD("endAllActiveAnimators on %p (%s) with handle %p",
- &mParent, mParent.getName(), mAnimationHandle);
+ ALOGD("endAllActiveAnimators on %p (%s) with handle %p", &mParent, mParent.getName(),
+ mAnimationHandle);
EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
for_each(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.clear();
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
index 8e6f820608b5..9575391a8b3f 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -34,6 +34,7 @@ class TreeInfo;
// Responsible for managing the animators for a single RenderNode
class AnimatorManager {
PREVENT_COPY_AND_ASSIGN(AnimatorManager);
+
public:
explicit AnimatorManager(RenderNode& parent);
~AnimatorManager();
@@ -68,8 +69,8 @@ private:
AnimationHandle* mAnimationHandle;
// To improve the efficiency of resizing & removing from the vector
- std::vector< sp<BaseRenderNodeAnimator> > mNewAnimators;
- std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
+ std::vector<sp<BaseRenderNodeAnimator> > mNewAnimators;
+ std::vector<sp<BaseRenderNodeAnimator> > mAnimators;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 03a397c1084d..f78cb418c5cd 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -23,29 +23,28 @@
#include "GlopBuilder.h"
#include "Patch.h"
#include "PathTessellator.h"
+#include "VertexBuffer.h"
#include "renderstate/OffscreenBufferPool.h"
#include "renderstate/RenderState.h"
#include "utils/GLUtils.h"
-#include "VertexBuffer.h"
-#include <algorithm>
-#include <math.h>
#include <SkPaintDefaults.h>
#include <SkPathOps.h>
+#include <math.h>
+#include <algorithm>
namespace android {
namespace uirenderer {
static void storeTexturedRect(TextureVertex* vertices, const Rect& bounds) {
- vertices[0] = { bounds.left, bounds.top, 0, 0 };
- vertices[1] = { bounds.right, bounds.top, 1, 0 };
- vertices[2] = { bounds.left, bounds.bottom, 0, 1 };
- vertices[3] = { bounds.right, bounds.bottom, 1, 1 };
+ vertices[0] = {bounds.left, bounds.top, 0, 0};
+ vertices[1] = {bounds.right, bounds.top, 1, 0};
+ vertices[2] = {bounds.left, bounds.bottom, 0, 1};
+ vertices[3] = {bounds.right, bounds.bottom, 1, 1};
}
void BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer,
- const MergedBakedOpList& opList) {
-
+ const MergedBakedOpList& opList) {
const BakedOpState& firstState = *(opList.states[0]);
Bitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap;
@@ -70,7 +69,8 @@ void BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer,
}
const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
+ ? TextureFillFlags::IsAlphaMaskTexture
+ : TextureFillFlags::None;
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(firstState.roundRectClipState)
@@ -85,7 +85,7 @@ void BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer,
}
void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
- const MergedBakedOpList& opList) {
+ const MergedBakedOpList& opList) {
const PatchOp& firstOp = *(static_cast<const PatchOp*>(opList.states[0]->op));
const BakedOpState& firstState = *(opList.states[0]);
@@ -99,8 +99,8 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
// TODO: cache mesh lookups
const Patch* opMesh = renderer.caches().patchCache.get(
- op.bitmap->width(), op.bitmap->height(),
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
+ op.bitmap->width(), op.bitmap->height(), op.unmappedBounds.getWidth(),
+ op.unmappedBounds.getHeight(), op.patch);
totalVertices += opMesh->verticesCount;
}
@@ -120,9 +120,8 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
// TODO: cache mesh lookups
const Patch* opMesh = renderer.caches().patchCache.get(
- op.bitmap->width(), op.bitmap->height(),
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
-
+ op.bitmap->width(), op.bitmap->height(), op.unmappedBounds.getWidth(),
+ op.unmappedBounds.getHeight(), op.patch);
uint32_t vertexCount = opMesh->verticesCount;
if (vertexCount == 0) continue;
@@ -130,17 +129,16 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
// We use the bounds to know where to translate our vertices
// Using patchOp->state.mBounds wouldn't work because these
// bounds are clipped
- const float tx = floorf(state.computedState.transform.getTranslateX()
- + op.unmappedBounds.left + 0.5f);
- const float ty = floorf(state.computedState.transform.getTranslateY()
- + op.unmappedBounds.top + 0.5f);
+ const float tx = floorf(state.computedState.transform.getTranslateX() +
+ op.unmappedBounds.left + 0.5f);
+ const float ty = floorf(state.computedState.transform.getTranslateY() +
+ op.unmappedBounds.top + 0.5f);
// Copy & transform all the vertices for the current operation
TextureVertex* opVertices = opMesh->vertices.get();
for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
- TextureVertex::set(vertex++,
- opVertices->x + tx, opVertices->y + ty,
- opVertices->u, opVertices->v);
+ TextureVertex::set(vertex++, opVertices->x + tx, opVertices->y + ty, opVertices->u,
+ opVertices->v);
}
// Dirty the current layer if possible. When the 9-patch does not
@@ -148,16 +146,16 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
// dirty rect to the object's bounds.
if (dirtyRenderTarget) {
if (!opMesh->hasEmptyQuads) {
- renderer.dirtyRenderTarget(Rect(tx, ty,
- tx + op.unmappedBounds.getWidth(), ty + op.unmappedBounds.getHeight()));
+ renderer.dirtyRenderTarget(Rect(tx, ty, tx + op.unmappedBounds.getWidth(),
+ ty + op.unmappedBounds.getHeight()));
} else {
const size_t count = opMesh->quads.size();
for (size_t i = 0; i < count; i++) {
const Rect& quadBounds = opMesh->quads[i];
const float x = tx + quadBounds.left;
const float y = ty + quadBounds.top;
- renderer.dirtyRenderTarget(Rect(x, y,
- x + quadBounds.getWidth(), y + quadBounds.getHeight()));
+ renderer.dirtyRenderTarget(
+ Rect(x, y, x + quadBounds.getWidth(), y + quadBounds.getHeight()));
}
}
}
@@ -165,7 +163,6 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
indexCount += opMesh->indexCount;
}
-
Texture* texture = renderer.caches().textureCache.get(firstOp.bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
@@ -188,8 +185,8 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
renderer.renderGlop(nullptr, clip, glop);
}
-static void renderTextShadow(BakedOpRenderer& renderer,
- const TextOp& op, const BakedOpState& textOpState) {
+static void renderTextShadow(BakedOpRenderer& renderer, const TextOp& op,
+ const BakedOpState& textOpState) {
if (CC_LIKELY(!PaintUtils::hasTextShadow(op.paint))) return;
FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer();
@@ -225,7 +222,7 @@ static void renderTextShadow(BakedOpRenderer& renderer,
// Bounds should be same as text op, but with dx/dy offset and radius outset
// applied in local space.
auto& transform = textOpState.computedState.transform;
- Rect shadowBounds = op.unmappedBounds; // STROKE
+ Rect shadowBounds = op.unmappedBounds; // STROKE
const bool expandForStroke = op.paint->getStyle() != SkPaint::kFill_Style;
if (expandForStroke) {
shadowBounds.outset(op.paint->getStrokeWidth() * 0.5f);
@@ -234,13 +231,12 @@ static void renderTextShadow(BakedOpRenderer& renderer,
shadowBounds.outset(textShadow.radius, textShadow.radius);
transform.mapRect(shadowBounds);
if (CC_UNLIKELY(expandForStroke &&
- (!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) {
+ (!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) {
shadowBounds.outset(0.5f);
}
auto clipState = textOpState.computedState.clipState;
- if (clipState->mode != ClipMode::Rectangle
- || !clipState->rect.contains(shadowBounds)) {
+ if (clipState->mode != ClipMode::Rectangle || !clipState->rect.contains(shadowBounds)) {
// need clip, so pass it and clip bounds
shadowBounds.doIntersect(clipState->rect);
} else {
@@ -251,13 +247,10 @@ static void renderTextShadow(BakedOpRenderer& renderer,
renderer.renderGlop(&shadowBounds, clipState, glop);
}
-enum class TextRenderType {
- Defer,
- Flush
-};
+enum class TextRenderType { Defer, Flush };
static void renderText(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state,
- const ClipBase* renderClip, TextRenderType renderType) {
+ const ClipBase* renderClip, TextRenderType renderType) {
FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer();
float x = op.x;
float y = op.y;
@@ -285,23 +278,23 @@ static void renderText(BakedOpRenderer& renderer, const TextOp& op, const BakedO
// font renderer which greatly simplifies the code, clipping in particular.
float sx, sy;
transform.decomposeScale(sx, sy);
- fontRenderer.setFont(op.paint, SkMatrix::MakeScale(
- roundf(std::max(1.0f, sx)),
- roundf(std::max(1.0f, sy))));
+ fontRenderer.setFont(op.paint, SkMatrix::MakeScale(roundf(std::max(1.0f, sx)),
+ roundf(std::max(1.0f, sy))));
fontRenderer.setTextureFiltering(true);
}
Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha;
SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint);
- TextDrawFunctor functor(&renderer, &state, renderClip,
- x, y, pureTranslate, alpha, mode, op.paint);
+ TextDrawFunctor functor(&renderer, &state, renderClip, x, y, pureTranslate, alpha, mode,
+ op.paint);
bool forceFinish = (renderType == TextRenderType::Flush);
bool mustDirtyRenderTarget = renderer.offscreenRenderTarget();
const Rect* localOpClip = pureTranslate ? &state.computedState.clipRect() : nullptr;
- fontRenderer.renderPosText(op.paint, localOpClip, op.glyphs, op.glyphCount, x, y,
- op.positions, mustDirtyRenderTarget ? &layerBounds : nullptr, &functor, forceFinish);
+ fontRenderer.renderPosText(op.paint, localOpClip, op.glyphs, op.glyphCount, x, y, op.positions,
+ mustDirtyRenderTarget ? &layerBounds : nullptr, &functor,
+ forceFinish);
if (mustDirtyRenderTarget) {
if (!pureTranslate) {
@@ -312,7 +305,7 @@ static void renderText(BakedOpRenderer& renderer, const TextOp& op, const BakedO
}
void BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer,
- const MergedBakedOpList& opList) {
+ const MergedBakedOpList& opList) {
for (size_t i = 0; i < opList.count; i++) {
const BakedOpState& state = *(opList.states[i]);
const TextOp& op = *(static_cast<const TextOp*>(state.op));
@@ -324,26 +317,27 @@ void BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer,
for (size_t i = 0; i < opList.count; i++) {
const BakedOpState& state = *(opList.states[i]);
const TextOp& op = *(static_cast<const TextOp*>(state.op));
- TextRenderType renderType = (i + 1 == opList.count)
- ? TextRenderType::Flush : TextRenderType::Defer;
+ TextRenderType renderType =
+ (i + 1 == opList.count) ? TextRenderType::Flush : TextRenderType::Defer;
renderText(renderer, op, state, clip, renderType);
}
}
namespace VertexBufferRenderFlags {
- enum {
- Offset = 0x1,
- ShadowInterp = 0x2,
- };
+enum {
+ Offset = 0x1,
+ ShadowInterp = 0x2,
+};
}
static void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& state,
- const VertexBuffer& vertexBuffer, float translateX, float translateY,
- const SkPaint& paint, int vertexBufferRenderFlags) {
+ const VertexBuffer& vertexBuffer, float translateX, float translateY,
+ const SkPaint& paint, int vertexBufferRenderFlags) {
if (CC_LIKELY(vertexBuffer.getVertexCount())) {
bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp;
const int transformFlags = vertexBufferRenderFlags & VertexBufferRenderFlags::Offset
- ? TransformFlags::OffsetByFudgeFactor : 0;
+ ? TransformFlags::OffsetByFudgeFactor
+ : 0;
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
@@ -358,24 +352,23 @@ static void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& st
}
static void renderConvexPath(BakedOpRenderer& renderer, const BakedOpState& state,
- const SkPath& path, const SkPaint& paint) {
+ const SkPath& path, const SkPaint& paint) {
VertexBuffer vertexBuffer;
// TODO: try clipping large paths to viewport
PathTessellator::tessellatePath(path, &paint, state.computedState.transform, vertexBuffer);
renderVertexBuffer(renderer, state, vertexBuffer, 0.0f, 0.0f, paint, 0);
}
-static void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state,
- float xOffset, float yOffset, PathTexture& texture, const SkPaint& paint) {
+static void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state, float xOffset,
+ float yOffset, PathTexture& texture, const SkPaint& paint) {
Rect dest(texture.width(), texture.height());
- dest.translate(xOffset + texture.left - texture.offset,
- yOffset + texture.top - texture.offset);
+ dest.translate(xOffset + texture.left - texture.offset, yOffset + texture.top - texture.offset);
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
.setMeshTexturedUnitQuad(nullptr)
.setFillPathTexturePaint(texture, paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
+ .setTransform(state.computedState.transform, TransformFlags::None)
.setModelViewMapUnitToRect(dest)
.build();
renderer.renderGlop(state, glop);
@@ -390,18 +383,18 @@ SkRect getBoundsOfFill(const RecordedOp& op) {
return bounds;
}
-void BakedOpDispatcher::onArcOp(BakedOpRenderer& renderer, const ArcOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onArcOp(BakedOpRenderer& renderer, const ArcOp& op,
+ const BakedOpState& state) {
// TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
- if (op.paint->getStyle() != SkPaint::kStroke_Style
- || op.paint->getPathEffect() != nullptr
- || op.useCenter) {
+ if (op.paint->getStyle() != SkPaint::kStroke_Style || op.paint->getPathEffect() != nullptr ||
+ op.useCenter) {
PathTexture* texture = renderer.caches().pathCache.getArc(
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(),
- op.startAngle, op.sweepAngle, op.useCenter, op.paint);
+ op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.startAngle,
+ op.sweepAngle, op.useCenter, op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
+ *texture, *(op.paint));
}
} else {
SkRect rect = getBoundsOfFill(op);
@@ -417,13 +410,15 @@ void BakedOpDispatcher::onArcOp(BakedOpRenderer& renderer, const ArcOp& op, cons
}
}
-void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op,
+ const BakedOpState& state) {
Texture* texture = renderer.getTexture(op.bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
+ ? TextureFillFlags::IsAlphaMaskTexture
+ : TextureFillFlags::None;
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
@@ -435,7 +430,8 @@ void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op
renderer.renderGlop(state, glop);
}
-void BakedOpDispatcher::onBitmapMeshOp(BakedOpRenderer& renderer, const BitmapMeshOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onBitmapMeshOp(BakedOpRenderer& renderer, const BitmapMeshOp& op,
+ const BakedOpState& state) {
Texture* texture = renderer.caches().textureCache.get(op.bitmap);
if (!texture) {
return;
@@ -495,13 +491,14 @@ void BakedOpDispatcher::onBitmapMeshOp(BakedOpRenderer& renderer, const BitmapMe
.setRoundRectClipState(state.roundRectClipState)
.setMeshColoredTexturedMesh(mesh.get(), elementCount)
.setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
+ .setTransform(state.computedState.transform, TransformFlags::None)
.setModelViewOffsetRect(0, 0, op.unmappedBounds)
.build();
renderer.renderGlop(state, glop);
}
-void BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRectOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRectOp& op,
+ const BakedOpState& state) {
Texture* texture = renderer.getTexture(op.bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
@@ -512,9 +509,10 @@ void BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRe
std::min(1.0f, op.src.bottom / texture->height()));
const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
- const bool tryToSnap = MathUtils::areEqual(op.src.getWidth(), op.unmappedBounds.getWidth())
- && MathUtils::areEqual(op.src.getHeight(), op.unmappedBounds.getHeight());
+ ? TextureFillFlags::IsAlphaMaskTexture
+ : TextureFillFlags::None;
+ const bool tryToSnap = MathUtils::areEqual(op.src.getWidth(), op.unmappedBounds.getWidth()) &&
+ MathUtils::areEqual(op.src.getHeight(), op.unmappedBounds.getHeight());
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
@@ -526,7 +524,8 @@ void BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRe
renderer.renderGlop(state, glop);
}
-void BakedOpDispatcher::onColorOp(BakedOpRenderer& renderer, const ColorOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onColorOp(BakedOpRenderer& renderer, const ColorOp& op,
+ const BakedOpState& state) {
SkPaint paint;
paint.setColor(op.color);
paint.setBlendMode(op.mode);
@@ -542,26 +541,29 @@ void BakedOpDispatcher::onColorOp(BakedOpRenderer& renderer, const ColorOp& op,
renderer.renderGlop(state, glop);
}
-void BakedOpDispatcher::onFunctorOp(BakedOpRenderer& renderer, const FunctorOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onFunctorOp(BakedOpRenderer& renderer, const FunctorOp& op,
+ const BakedOpState& state) {
renderer.renderFunctor(op, state);
}
-void BakedOpDispatcher::onLinesOp(BakedOpRenderer& renderer, const LinesOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onLinesOp(BakedOpRenderer& renderer, const LinesOp& op,
+ const BakedOpState& state) {
VertexBuffer buffer;
PathTessellator::tessellateLines(op.points, op.floatCount, op.paint,
- state.computedState.transform, buffer);
+ state.computedState.transform, buffer);
int displayFlags = op.paint->isAntiAlias() ? 0 : VertexBufferRenderFlags::Offset;
renderVertexBuffer(renderer, state, buffer, 0, 0, *(op.paint), displayFlags);
}
-void BakedOpDispatcher::onOvalOp(BakedOpRenderer& renderer, const OvalOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onOvalOp(BakedOpRenderer& renderer, const OvalOp& op,
+ const BakedOpState& state) {
if (op.paint->getPathEffect() != nullptr) {
PathTexture* texture = renderer.caches().pathCache.getOval(
op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
+ *texture, *(op.paint));
}
} else {
SkPath path;
@@ -577,7 +579,8 @@ void BakedOpDispatcher::onOvalOp(BakedOpRenderer& renderer, const OvalOp& op, co
}
}
-void BakedOpDispatcher::onPatchOp(BakedOpRenderer& renderer, const PatchOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onPatchOp(BakedOpRenderer& renderer, const PatchOp& op,
+ const BakedOpState& state) {
// 9 patches are built for stretching - always filter
int textureFillFlags = TextureFillFlags::ForceFilter;
if (op.bitmap->colorType() == kAlpha_8_SkColorType) {
@@ -585,9 +588,9 @@ void BakedOpDispatcher::onPatchOp(BakedOpRenderer& renderer, const PatchOp& op,
}
// TODO: avoid redoing the below work each frame:
- const Patch* mesh = renderer.caches().patchCache.get(
- op.bitmap->width(), op.bitmap->height(),
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
+ const Patch* mesh = renderer.caches().patchCache.get(op.bitmap->width(), op.bitmap->height(),
+ op.unmappedBounds.getWidth(),
+ op.unmappedBounds.getHeight(), op.patch);
Texture* texture = renderer.caches().textureCache.get(op.bitmap);
if (CC_LIKELY(texture)) {
@@ -598,14 +601,16 @@ void BakedOpDispatcher::onPatchOp(BakedOpRenderer& renderer, const PatchOp& op,
.setMeshPatchQuads(*mesh)
.setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
.setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
+ .setModelViewOffsetRectSnap(
+ op.unmappedBounds.left, op.unmappedBounds.top,
Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
.build();
renderer.renderGlop(state, glop);
}
}
-void BakedOpDispatcher::onPathOp(BakedOpRenderer& renderer, const PathOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onPathOp(BakedOpRenderer& renderer, const PathOp& op,
+ const BakedOpState& state) {
PathTexture* texture = renderer.caches().pathCache.get(op.path, op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
@@ -615,10 +620,11 @@ void BakedOpDispatcher::onPathOp(BakedOpRenderer& renderer, const PathOp& op, co
}
}
-void BakedOpDispatcher::onPointsOp(BakedOpRenderer& renderer, const PointsOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onPointsOp(BakedOpRenderer& renderer, const PointsOp& op,
+ const BakedOpState& state) {
VertexBuffer buffer;
PathTessellator::tessellatePoints(op.points, op.floatCount, op.paint,
- state.computedState.transform, buffer);
+ state.computedState.transform, buffer);
int displayFlags = op.paint->isAntiAlias() ? 0 : VertexBufferRenderFlags::Offset;
renderVertexBuffer(renderer, state, buffer, 0, 0, *(op.paint), displayFlags);
}
@@ -626,20 +632,21 @@ void BakedOpDispatcher::onPointsOp(BakedOpRenderer& renderer, const PointsOp& op
// See SkPaintDefaults.h
#define SkPaintDefaults_MiterLimit SkIntToScalar(4)
-void BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op,
+ const BakedOpState& state) {
if (op.paint->getStyle() != SkPaint::kFill_Style) {
// only fill + default miter is supported by drawConvexPath, since others must handle joins
static_assert(SkPaintDefaults_MiterLimit == 4.0f, "Miter limit has changed");
- if (CC_UNLIKELY(op.paint->getPathEffect() != nullptr
- || op.paint->getStrokeJoin() != SkPaint::kMiter_Join
- || op.paint->getStrokeMiter() != SkPaintDefaults_MiterLimit)) {
- PathTexture* texture = renderer.caches().pathCache.getRect(
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
- const AutoTexture holder(texture);
- if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
- }
+ if (CC_UNLIKELY(op.paint->getPathEffect() != nullptr ||
+ op.paint->getStrokeJoin() != SkPaint::kMiter_Join ||
+ op.paint->getStrokeMiter() != SkPaintDefaults_MiterLimit)) {
+ PathTexture* texture = renderer.caches().pathCache.getRect(
+ op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
+ const AutoTexture holder(texture);
+ if (CC_LIKELY(holder.texture)) {
+ renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
+ *texture, *(op.paint));
+ }
} else {
SkPath path;
path.addRect(getBoundsOfFill(op));
@@ -665,29 +672,31 @@ void BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, co
}
}
-void BakedOpDispatcher::onRoundRectOp(BakedOpRenderer& renderer, const RoundRectOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onRoundRectOp(BakedOpRenderer& renderer, const RoundRectOp& op,
+ const BakedOpState& state) {
if (op.paint->getPathEffect() != nullptr) {
PathTexture* texture = renderer.caches().pathCache.getRoundRect(
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(),
- op.rx, op.ry, op.paint);
+ op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.rx, op.ry,
+ op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
- *texture, *(op.paint));
+ *texture, *(op.paint));
}
} else {
const VertexBuffer* buffer = renderer.caches().tessellationCache.getRoundRect(
- state.computedState.transform, *(op.paint),
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.rx, op.ry);
- renderVertexBuffer(renderer, state, *buffer,
- op.unmappedBounds.left, op.unmappedBounds.top, *(op.paint), 0);
+ state.computedState.transform, *(op.paint), op.unmappedBounds.getWidth(),
+ op.unmappedBounds.getHeight(), op.rx, op.ry);
+ renderVertexBuffer(renderer, state, *buffer, op.unmappedBounds.left, op.unmappedBounds.top,
+ *(op.paint), 0);
}
}
static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha,
- const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) {
+ const VertexBuffer* ambientShadowVertexBuffer,
+ const VertexBuffer* spotShadowVertexBuffer) {
SkPaint paint;
- paint.setAntiAlias(true); // want to use AlphaVertex
+ paint.setAntiAlias(true); // want to use AlphaVertex
// The caller has made sure casterAlpha > 0.
uint8_t ambientShadowAlpha = renderer.getLightInfo().ambientShadowAlpha;
@@ -696,8 +705,8 @@ static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, f
}
if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) {
paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha));
- renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0,
- paint, VertexBufferRenderFlags::ShadowInterp);
+ renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0, paint,
+ VertexBufferRenderFlags::ShadowInterp);
}
uint8_t spotShadowAlpha = renderer.getLightInfo().spotShadowAlpha;
@@ -706,17 +715,19 @@ static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, f
}
if (spotShadowVertexBuffer && spotShadowAlpha > 0) {
paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha));
- renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0,
- paint, VertexBufferRenderFlags::ShadowInterp);
+ renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0, paint,
+ VertexBufferRenderFlags::ShadowInterp);
}
}
-void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op,
+ const BakedOpState& state) {
TessellationCache::vertexBuffer_pair_t buffers = op.shadowTask->getResult();
renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second);
}
-void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op,
+ const BakedOpState& state) {
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
@@ -728,12 +739,14 @@ void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleR
renderer.renderGlop(state, glop);
}
-void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op,
+ const BakedOpState& state) {
renderTextShadow(renderer, op, state);
renderText(renderer, op, state, state.computedState.getClipIfNeeded(), TextRenderType::Flush);
}
-void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op,
+ const BakedOpState& state) {
// Note: can't trust clipSideFlags since we record with unmappedBounds == clip.
// TODO: respect clipSideFlags, once we record with bounds
auto renderTargetClip = state.computedState.clipState;
@@ -746,14 +759,14 @@ void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPa
int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha;
SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint);
- TextDrawFunctor functor(&renderer, &state, renderTargetClip,
- 0.0f, 0.0f, false, alpha, mode, op.paint);
+ TextDrawFunctor functor(&renderer, &state, renderTargetClip, 0.0f, 0.0f, false, alpha, mode,
+ op.paint);
bool mustDirtyRenderTarget = renderer.offscreenRenderTarget();
const Rect localSpaceClip = state.computedState.computeLocalSpaceClip();
- if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip, op.glyphs, op.glyphCount,
- op.path, op.hOffset, op.vOffset,
- mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) {
+ if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip, op.glyphs, op.glyphCount, op.path,
+ op.hOffset, op.vOffset,
+ mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) {
if (mustDirtyRenderTarget) {
// manually dirty render target, since TextDrawFunctor won't
state.computedState.transform.mapRect(layerBounds);
@@ -762,7 +775,8 @@ void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPa
}
}
-void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op,
+ const BakedOpState& state) {
GlLayer* layer = static_cast<GlLayer*>(op.layerHandle->backingLayer());
if (!layer) {
return;
@@ -772,16 +786,17 @@ void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const Textur
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
- .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
+ .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
.setFillTextureLayer(*(layer), alpha)
.setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewMapUnitToRectOptionalSnap(tryToSnap, Rect(layer->getWidth(), layer->getHeight()))
+ .setModelViewMapUnitToRectOptionalSnap(tryToSnap,
+ Rect(layer->getWidth(), layer->getHeight()))
.build();
renderer.renderGlop(state, glop);
}
void renderRectForLayer(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state,
- int color, SkBlendMode mode, SkColorFilter* colorFilter) {
+ int color, SkBlendMode mode, SkColorFilter* colorFilter) {
SkPaint paint;
paint.setColor(color);
paint.setBlendMode(mode);
@@ -790,7 +805,8 @@ void renderRectForLayer(BakedOpRenderer& renderer, const LayerOp& op, const Bake
BakedOpDispatcher::onRectOp(renderer, rectOp, state);
}
-void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op,
+ const BakedOpState& state) {
// Note that we don't use op->paint in this function - it's never set on a LayerOp
OffscreenBuffer* buffer = *op.layerHandle;
@@ -801,9 +817,11 @@ void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op,
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
.setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount)
- .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap)
+ .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode,
+ Blend::ModeOrderSwap::NoSwap)
.setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
+ .setModelViewOffsetRectSnap(
+ op.unmappedBounds.left, op.unmappedBounds.top,
Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
.build();
renderer.renderGlop(state, glop);
@@ -812,23 +830,24 @@ void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op,
buffer->hasRenderedSinceRepaint = true;
if (CC_UNLIKELY(Properties::debugLayersUpdates)) {
// render debug layer highlight
- renderRectForLayer(renderer, op, state,
- 0x7f00ff00, SkBlendMode::kSrcOver, nullptr);
+ renderRectForLayer(renderer, op, state, 0x7f00ff00, SkBlendMode::kSrcOver, nullptr);
} else if (CC_UNLIKELY(Properties::debugOverdraw)) {
// render transparent to increment overdraw for repaint area
- renderRectForLayer(renderer, op, state,
- SK_ColorTRANSPARENT, SkBlendMode::kSrcOver, nullptr);
+ renderRectForLayer(renderer, op, state, SK_ColorTRANSPARENT, SkBlendMode::kSrcOver,
+ nullptr);
}
}
}
-void BakedOpDispatcher::onCopyToLayerOp(BakedOpRenderer& renderer, const CopyToLayerOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onCopyToLayerOp(BakedOpRenderer& renderer, const CopyToLayerOp& op,
+ const BakedOpState& state) {
LOG_ALWAYS_FATAL_IF(*(op.layerHandle) != nullptr, "layer already exists!");
*(op.layerHandle) = renderer.copyToLayer(state.computedState.clippedBounds);
LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "layer copy failed");
}
-void BakedOpDispatcher::onCopyFromLayerOp(BakedOpRenderer& renderer, const CopyFromLayerOp& op, const BakedOpState& state) {
+void BakedOpDispatcher::onCopyFromLayerOp(BakedOpRenderer& renderer, const CopyFromLayerOp& op,
+ const BakedOpState& state) {
LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "no layer to draw underneath!");
if (!state.computedState.clippedBounds.isEmpty()) {
if (op.paint && op.paint->getAlpha() < 255) {
@@ -836,7 +855,8 @@ void BakedOpDispatcher::onCopyFromLayerOp(BakedOpRenderer& renderer, const CopyF
layerPaint.setAlpha(op.paint->getAlpha());
layerPaint.setBlendMode(SkBlendMode::kDstIn);
layerPaint.setColorFilter(sk_ref_sp(op.paint->getColorFilter()));
- RectOp rectOp(state.computedState.clippedBounds, Matrix4::identity(), nullptr, &layerPaint);
+ RectOp rectOp(state.computedState.clippedBounds, Matrix4::identity(), nullptr,
+ &layerPaint);
BakedOpDispatcher::onRectOp(renderer, rectOp, state);
}
@@ -855,5 +875,5 @@ void BakedOpDispatcher::onCopyFromLayerOp(BakedOpRenderer& renderer, const CopyF
renderer.renderState().layerPool().putOrDelete(*op.layerHandle);
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/BakedOpDispatcher.h b/libs/hwui/BakedOpDispatcher.h
index 4dfdd3ff619a..e3708685afc9 100644
--- a/libs/hwui/BakedOpDispatcher.h
+++ b/libs/hwui/BakedOpDispatcher.h
@@ -33,21 +33,20 @@ namespace uirenderer {
*/
class BakedOpDispatcher {
public:
- // Declares all "onMergedBitmapOps(...)" style methods for mergeable op types
+// Declares all "onMergedBitmapOps(...)" style methods for mergeable op types
#define X(Type) \
- static void onMerged##Type##s(BakedOpRenderer& renderer, const MergedBakedOpList& opList);
+ static void onMerged##Type##s(BakedOpRenderer& renderer, const MergedBakedOpList& opList);
MAP_MERGEABLE_OPS(X)
#undef X
- // Declares all "onBitmapOp(...)" style methods for every op type
+// Declares all "onBitmapOp(...)" style methods for every op type
#define X(Type) \
- static void on##Type(BakedOpRenderer& renderer, const Type& op, const BakedOpState& state);
+ static void on##Type(BakedOpRenderer& renderer, const Type& op, const BakedOpState& state);
MAP_RENDERABLE_OPS(X)
#undef X
-
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_BAKED_OP_DISPATCHER_H
+#endif // ANDROID_HWUI_BAKED_OP_DISPATCHER_H
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 3c3b3177159b..6b64b94d291e 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -19,10 +19,10 @@
#include "Caches.h"
#include "Glop.h"
#include "GlopBuilder.h"
+#include "VertexBuffer.h"
#include "renderstate/OffscreenBufferPool.h"
#include "renderstate/RenderState.h"
#include "utils/GLUtils.h"
-#include "VertexBuffer.h"
#include <algorithm>
@@ -32,8 +32,8 @@ namespace uirenderer {
OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t height) {
LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
- OffscreenBuffer* buffer = mRenderState.layerPool().get(
- mRenderState, width, height, mWideColorGamut);
+ OffscreenBuffer* buffer =
+ mRenderState.layerPool().get(mRenderState, width, height, mWideColorGamut);
startRepaintLayer(buffer, Rect(width, height));
return buffer;
}
@@ -46,13 +46,13 @@ void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const
LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
// subtract repaintRect from region, since it will be regenerated
- if (repaintRect.contains(0, 0,
- offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight)) {
+ if (repaintRect.contains(0, 0, offscreenBuffer->viewportWidth,
+ offscreenBuffer->viewportHeight)) {
// repaint full layer, so throw away entire region
offscreenBuffer->region.clear();
} else {
offscreenBuffer->region.subtractSelf(android::Rect(repaintRect.left, repaintRect.top,
- repaintRect.right, repaintRect.bottom));
+ repaintRect.right, repaintRect.bottom));
}
mRenderTarget.offscreenBuffer = offscreenBuffer;
@@ -64,16 +64,14 @@ void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const
// attach the texture to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- offscreenBuffer->texture.id(), 0);
+ offscreenBuffer->texture.id(), 0);
GL_CHECKPOINT(LOW);
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
LOG_ALWAYS_FATAL_IF(status != GL_FRAMEBUFFER_COMPLETE,
- "framebuffer incomplete, status %d, textureId %d, size %dx%d",
- status,
- offscreenBuffer->texture.id(),
- offscreenBuffer->texture.width(),
- offscreenBuffer->texture.height());
+ "framebuffer incomplete, status %d, textureId %d, size %dx%d", status,
+ offscreenBuffer->texture.id(), offscreenBuffer->texture.width(),
+ offscreenBuffer->texture.height());
// Change the viewport & ortho projection
setViewport(offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight);
@@ -92,7 +90,7 @@ void BakedOpRenderer::endLayer() {
mRenderTarget.lastStencilClip = nullptr;
mRenderTarget.offscreenBuffer->updateMeshFromRegion();
- mRenderTarget.offscreenBuffer = nullptr; // It's in drawLayerOp's hands now.
+ mRenderTarget.offscreenBuffer = nullptr; // It's in drawLayerOp's hands now.
// Detach the texture from the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
@@ -104,14 +102,14 @@ void BakedOpRenderer::endLayer() {
OffscreenBuffer* BakedOpRenderer::copyToLayer(const Rect& area) {
const uint32_t width = area.getWidth();
const uint32_t height = area.getHeight();
- OffscreenBuffer* buffer = mRenderState.layerPool().get(
- mRenderState, width, height, mWideColorGamut);
+ OffscreenBuffer* buffer =
+ mRenderState.layerPool().get(mRenderState, width, height, mWideColorGamut);
if (!area.isEmpty() && width != 0 && height != 0) {
mCaches.textureState().activateTexture(0);
mCaches.textureState().bindTexture(buffer->texture.id());
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
- area.left, mRenderTarget.viewportHeight - area.bottom, width, height);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, area.left,
+ mRenderTarget.viewportHeight - area.bottom, width, height);
}
return buffer;
}
@@ -177,7 +175,7 @@ void BakedOpRenderer::clearColorBuffer(const Rect& rect) {
// Requested rect is subset of viewport - scissor to it to avoid over-clearing
mRenderState.scissor().setEnabled(true);
mRenderState.scissor().set(rect.left, mRenderTarget.viewportHeight - rect.bottom,
- rect.getWidth(), rect.getHeight());
+ rect.getWidth(), rect.getHeight());
}
glClear(GL_COLOR_BUFFER_BIT);
if (!mRenderTarget.frameBufferId) mHasDrawn = true;
@@ -222,8 +220,7 @@ void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* pa
// clears and re-fills stencil with provided rendertarget space quads,
// and then put stencil into test mode
-void BakedOpRenderer::setupStencilQuads(std::vector<Vertex>& quadVertices,
- int incrementThreshold) {
+void BakedOpRenderer::setupStencilQuads(std::vector<Vertex>& quadVertices, int incrementThreshold) {
mRenderState.stencil().enableWrite(incrementThreshold);
mRenderState.stencil().clear();
Glop glop;
@@ -239,7 +236,8 @@ void BakedOpRenderer::setupStencilQuads(std::vector<Vertex>& quadVertices,
}
void BakedOpRenderer::setupStencilRectList(const ClipBase* clip) {
- LOG_ALWAYS_FATAL_IF(clip->mode != ClipMode::RectangleList, "can't rectlist clip without rectlist");
+ LOG_ALWAYS_FATAL_IF(clip->mode != ClipMode::RectangleList,
+ "can't rectlist clip without rectlist");
auto&& rectList = reinterpret_cast<const ClipRectList*>(clip)->rectList;
int quadCount = rectList.getTransformedRectanglesCount();
std::vector<Vertex> rectangleVertices;
@@ -253,7 +251,7 @@ void BakedOpRenderer::setupStencilRectList(const ClipBase* clip) {
transform.mapRect(bounds);
bounds.doIntersect(clip->rect);
if (bounds.isEmpty()) {
- continue; // will be outside of scissor, skip
+ continue; // will be outside of scissor, skip
}
}
@@ -309,11 +307,11 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli
if (mRenderTarget.frameBufferId != 0 && !mRenderTarget.stencil) {
OffscreenBuffer* layer = mRenderTarget.offscreenBuffer;
mRenderTarget.stencil = mCaches.renderBufferCache.get(
- Stencil::getLayerStencilFormat(),
- layer->texture.width(), layer->texture.height());
+ Stencil::getLayerStencilFormat(), layer->texture.width(),
+ layer->texture.height());
// stencil is bound + allocated - associate it with current FBO
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, mRenderTarget.stencil->getName());
+ GL_RENDERBUFFER, mRenderTarget.stencil->getName());
}
if (clip->mode == ClipMode::RectangleList) {
@@ -344,17 +342,15 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli
}
void BakedOpRenderer::renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip,
- const Glop& glop) {
+ const Glop& glop) {
prepareRender(dirtyBounds, clip);
// Disable blending if this is the first draw to the main framebuffer, in case app has defined
// transparency where it doesn't make sense - as first draw in opaque window. Note that we only
// apply this improvement when the blend mode is SRC_OVER - other modes (e.g. CLEAR) can be
// valid draws that affect other content (e.g. draw CLEAR, then draw DST_OVER)
- bool overrideDisableBlending = !mHasDrawn
- && mOpaque
- && !mRenderTarget.frameBufferId
- && glop.blend.src == GL_ONE
- && glop.blend.dst == GL_ONE_MINUS_SRC_ALPHA;
+ bool overrideDisableBlending = !mHasDrawn && mOpaque && !mRenderTarget.frameBufferId &&
+ glop.blend.src == GL_ONE &&
+ glop.blend.dst == GL_ONE_MINUS_SRC_ALPHA;
mRenderState.render(glop, mRenderTarget.orthoMatrix, overrideDisableBlending);
if (!mRenderTarget.frameBufferId) mHasDrawn = true;
}
@@ -383,5 +379,5 @@ void BakedOpRenderer::dirtyRenderTarget(const Rect& uiDirty) {
}
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 01ca36742d24..7c0590d7ab48 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -46,23 +46,20 @@ public:
*/
struct LightInfo {
LightInfo() : LightInfo(0, 0) {}
- LightInfo(uint8_t ambientShadowAlpha,
- uint8_t spotShadowAlpha)
- : ambientShadowAlpha(ambientShadowAlpha)
- , spotShadowAlpha(spotShadowAlpha) {}
+ LightInfo(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha)
+ : ambientShadowAlpha(ambientShadowAlpha), spotShadowAlpha(spotShadowAlpha) {}
uint8_t ambientShadowAlpha;
uint8_t spotShadowAlpha;
};
BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque, bool wideColorGamut,
- const LightInfo& lightInfo)
+ const LightInfo& lightInfo)
: mGlopReceiver(DefaultGlopReceiver)
, mRenderState(renderState)
, mCaches(caches)
, mOpaque(opaque)
, mWideColorGamut(wideColorGamut)
- , mLightInfo(lightInfo) {
- }
+ , mLightInfo(lightInfo) {}
RenderState& renderState() { return mRenderState; }
Caches& caches() { return mCaches; }
@@ -79,9 +76,7 @@ public:
const LightInfo& getLightInfo() const { return mLightInfo; }
void renderGlop(const BakedOpState& state, const Glop& glop) {
- renderGlop(&state.computedState.clippedBounds,
- state.computedState.getClipIfNeeded(),
- glop);
+ renderGlop(&state.computedState.clippedBounds, state.computedState.getClipIfNeeded(), glop);
}
void renderFunctor(const FunctorOp& op, const BakedOpState& state);
@@ -97,15 +92,17 @@ public:
// simple draw methods, to be used for end frame decoration
void drawRect(float left, float top, float right, float bottom, const SkPaint* paint) {
- float ltrb[4] = { left, top, right, bottom };
+ float ltrb[4] = {left, top, right, bottom};
drawRects(ltrb, 4, paint);
}
void drawRects(const float* rects, int count, const SkPaint* paint);
+
protected:
GlopReceiver mGlopReceiver;
+
private:
static void DefaultGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds,
- const ClipBase* clip, const Glop& glop) {
+ const ClipBase* clip, const Glop& glop) {
renderer.renderGlopImpl(dirtyBounds, clip, glop);
}
void renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop);
@@ -148,5 +145,5 @@ private:
const LightInfo mLightInfo;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 9823a02dc847..63edf77279e3 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -31,7 +31,8 @@ static int computeClipSideFlags(const Rect& clip, const Rect& bounds) {
}
ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
- const RecordedOp& recordedOp, bool expandForStroke, bool expandForPathTexture) {
+ const RecordedOp& recordedOp, bool expandForStroke,
+ bool expandForPathTexture) {
// resolvedMatrix = parentMatrix * localMatrix
transform.loadMultiply(*snapshot.transform, recordedOp.localMatrix);
@@ -44,16 +45,16 @@ ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& s
clippedBounds.outset(1);
}
transform.mapRect(clippedBounds);
- if (CC_UNLIKELY(expandForStroke
- && (!transform.isPureTranslate() || recordedOp.paint->getStrokeWidth() < 1.0f))) {
+ if (CC_UNLIKELY(expandForStroke &&
+ (!transform.isPureTranslate() || recordedOp.paint->getStrokeWidth() < 1.0f))) {
// account for hairline stroke when stroke may be < 1 scaled pixel
// Non translate || strokeWidth < 1 is conservative, but will cover all cases
clippedBounds.outset(0.5f);
}
// resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
- clipState = snapshot.serializeIntersectedClip(allocator,
- recordedOp.localClip, *(snapshot.transform));
+ clipState = snapshot.serializeIntersectedClip(allocator, recordedOp.localClip,
+ *(snapshot.transform));
LOG_ALWAYS_FATAL_IF(!clipState, "must clip!");
const Rect& clipRect = clipState->rect;
@@ -85,7 +86,7 @@ ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& s
}
ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
- const Matrix4& localTransform, const ClipBase* localClip) {
+ const Matrix4& localTransform, const ClipBase* localClip) {
transform.loadMultiply(*snapshot.transform, localTransform);
clipState = snapshot.serializeIntersectedClip(allocator, localClip, *(snapshot.transform));
clippedBounds = clipState->rect;
@@ -109,11 +110,11 @@ ResolvedRenderState::ResolvedRenderState(const ClipRect* clipRect, const Rect& d
clippedBounds.doIntersect(clipRect->rect);
}
-BakedOpState* BakedOpState::tryConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp) {
+BakedOpState* BakedOpState::tryConstruct(LinearAllocator& allocator, Snapshot& snapshot,
+ const RecordedOp& recordedOp) {
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
- BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
- allocator, snapshot, recordedOp, false, false);
+ BakedOpState* bakedState =
+ allocator.create_trivial<BakedOpState>(allocator, snapshot, recordedOp, false, false);
if (bakedState->computedState.clippedBounds.isEmpty()) {
// bounds are empty, so op is rejected
allocator.rewindIfLastAlloc(bakedState);
@@ -122,21 +123,23 @@ BakedOpState* BakedOpState::tryConstruct(LinearAllocator& allocator,
return bakedState;
}
-BakedOpState* BakedOpState::tryConstructUnbounded(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp) {
+BakedOpState* BakedOpState::tryConstructUnbounded(LinearAllocator& allocator, Snapshot& snapshot,
+ const RecordedOp& recordedOp) {
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
return allocator.create_trivial<BakedOpState>(allocator, snapshot, recordedOp);
}
-BakedOpState* BakedOpState::tryStrokeableOpConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior,
- bool expandForPathTexture) {
+BakedOpState* BakedOpState::tryStrokeableOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
+ const RecordedOp& recordedOp,
+ StrokeBehavior strokeBehavior,
+ bool expandForPathTexture) {
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
- bool expandForStroke = (strokeBehavior == StrokeBehavior::Forced
- || (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style));
+ bool expandForStroke =
+ (strokeBehavior == StrokeBehavior::Forced ||
+ (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style));
BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
- allocator, snapshot, recordedOp, expandForStroke, expandForPathTexture);
+ allocator, snapshot, recordedOp, expandForStroke, expandForPathTexture);
if (bakedState->computedState.clippedBounds.isEmpty()) {
// bounds are empty, so op is rejected
// NOTE: this won't succeed if a clip was allocated
@@ -146,26 +149,25 @@ BakedOpState* BakedOpState::tryStrokeableOpConstruct(LinearAllocator& allocator,
return bakedState;
}
-BakedOpState* BakedOpState::tryShadowOpConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
+BakedOpState* BakedOpState::tryShadowOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
+ const ShadowOp* shadowOpPtr) {
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
// clip isn't empty, so construct the op
return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
}
-BakedOpState* BakedOpState::directConstruct(LinearAllocator& allocator,
- const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
+BakedOpState* BakedOpState::directConstruct(LinearAllocator& allocator, const ClipRect* clip,
+ const Rect& dstRect, const RecordedOp& recordedOp) {
return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
}
void BakedOpState::setupOpacity(const SkPaint* paint) {
- computedState.opaqueOverClippedBounds = computedState.transform.isSimple()
- && computedState.clipState->mode == ClipMode::Rectangle
- && MathUtils::areEqual(alpha, 1.0f)
- && !roundRectClipState
- && PaintUtils::isOpaquePaint(paint);
+ computedState.opaqueOverClippedBounds = computedState.transform.isSimple() &&
+ computedState.clipState->mode == ClipMode::Rectangle &&
+ MathUtils::areEqual(alpha, 1.0f) &&
+ !roundRectClipState && PaintUtils::isOpaquePaint(paint);
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index 7b0b34f3d9c0..c74475516cdc 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -26,22 +26,22 @@ namespace android {
namespace uirenderer {
namespace OpClipSideFlags {
- enum {
- None = 0x0,
- Left = 0x1,
- Top = 0x2,
- Right = 0x4,
- Bottom = 0x8,
- Full = 0xF,
- // ConservativeFull = 0x1F needed?
- };
+enum {
+ None = 0x0,
+ Left = 0x1,
+ Top = 0x2,
+ Right = 0x4,
+ Bottom = 0x8,
+ Full = 0xF,
+ // ConservativeFull = 0x1F needed?
+};
}
/**
* Holds a list of BakedOpStates of ops that can be drawn together
*/
struct MergedBakedOpList {
- const BakedOpState*const* states;
+ const BakedOpState* const* states;
size_t count;
int clipSideFlags;
Rect clip;
@@ -53,11 +53,12 @@ struct MergedBakedOpList {
class ResolvedRenderState {
public:
ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
- const RecordedOp& recordedOp, bool expandForStroke, bool expandForPathTexture);
+ const RecordedOp& recordedOp, bool expandForStroke,
+ bool expandForPathTexture);
// Constructor for unbounded ops *with* transform/clip
ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
- const Matrix4& localTransform, const ClipBase* localClip);
+ const Matrix4& localTransform, const ClipBase* localClip);
// Constructor for unbounded ops without transform/clip (namely shadows)
ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot);
@@ -74,19 +75,15 @@ public:
return outClip;
}
- const Rect& clipRect() const {
- return clipState->rect;
- }
+ const Rect& clipRect() const { return clipState->rect; }
bool requiresClip() const {
- return clipSideFlags != OpClipSideFlags::None
- || CC_UNLIKELY(clipState->mode != ClipMode::Rectangle);
+ return clipSideFlags != OpClipSideFlags::None ||
+ CC_UNLIKELY(clipState->mode != ClipMode::Rectangle);
}
// returns the clip if it's needed to draw the operation, otherwise nullptr
- const ClipBase* getClipIfNeeded() const {
- return requiresClip() ? clipState : nullptr;
- }
+ const ClipBase* getClipIfNeeded() const { return requiresClip() ? clipState : nullptr; }
Matrix4 transform;
const ClipBase* clipState = nullptr;
@@ -103,11 +100,11 @@ public:
*/
class BakedOpState {
public:
- static BakedOpState* tryConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp);
+ static BakedOpState* tryConstruct(LinearAllocator& allocator, Snapshot& snapshot,
+ const RecordedOp& recordedOp);
- static BakedOpState* tryConstructUnbounded(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp);
+ static BakedOpState* tryConstructUnbounded(LinearAllocator& allocator, Snapshot& snapshot,
+ const RecordedOp& recordedOp);
enum class StrokeBehavior {
// stroking is forced, regardless of style on paint (such as for lines)
@@ -116,15 +113,16 @@ public:
StyleDefined,
};
- static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior,
- bool expandForPathTexture);
+ static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
+ const RecordedOp& recordedOp,
+ StrokeBehavior strokeBehavior,
+ bool expandForPathTexture);
- static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const ShadowOp* shadowOpPtr);
+ static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
+ const ShadowOp* shadowOpPtr);
- static BakedOpState* directConstruct(LinearAllocator& allocator,
- const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp);
+ static BakedOpState* directConstruct(LinearAllocator& allocator, const ClipRect* clip,
+ const Rect& dstRect, const RecordedOp& recordedOp);
// Set opaqueOverClippedBounds. If this method isn't called, the op is assumed translucent.
void setupOpacity(const SkPaint* paint);
@@ -140,8 +138,8 @@ public:
private:
friend class LinearAllocator;
- BakedOpState(LinearAllocator& allocator, Snapshot& snapshot,
- const RecordedOp& recordedOp, bool expandForStroke, bool expandForPathTexture)
+ BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const RecordedOp& recordedOp,
+ bool expandForStroke, bool expandForPathTexture)
: computedState(allocator, snapshot, recordedOp, expandForStroke, expandForPathTexture)
, alpha(snapshot.alpha)
, roundRectClipState(snapshot.roundRectClipState)
@@ -167,7 +165,7 @@ private:
, op(&recordedOp) {}
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_BAKED_OP_STATE_H
+#endif // ANDROID_HWUI_BAKED_OP_STATE_H
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 0700d1fb9f70..3c774a3313d2 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -19,8 +19,8 @@
#include "GammaFontRenderer.h"
#include "GlLayer.h"
#include "Properties.h"
-#include "renderstate/RenderState.h"
#include "ShadowTessellator.h"
+#include "renderstate/RenderState.h"
#ifdef BUGREPORT_FONT_CACHE_USAGE
#include "font/FontCacheHistoryTracker.h"
#endif
@@ -40,9 +40,9 @@ Caches* Caches::sInstance = nullptr;
///////////////////////////////////////////////////////////////////////////////
#if DEBUG_CACHE_FLUSH
- #define FLUSH_LOGD(...) ALOGD(__VA_ARGS__)
+#define FLUSH_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define FLUSH_LOGD(...)
+#define FLUSH_LOGD(...)
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -98,8 +98,8 @@ void Caches::initConstraints() {
void Caches::initStaticProperties() {
// OpenGL ES 3.0+ specific features
- gpuPixelBuffersEnabled = extensions().hasPixelBufferObjects()
- && property_get_bool(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, true);
+ gpuPixelBuffersEnabled = extensions().hasPixelBufferObjects() &&
+ property_get_bool(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, true);
}
void Caches::terminate() {
@@ -143,10 +143,8 @@ void Caches::setProgram(Program* program) {
///////////////////////////////////////////////////////////////////////////////
uint32_t Caches::getOverdrawColor(uint32_t amount) const {
- static uint32_t sOverdrawColors[2][4] = {
- { 0x2f0000ff, 0x2f00ff00, 0x3fff0000, 0x7fff0000 },
- { 0x2f0000ff, 0x4fffff00, 0x5fff8ad8, 0x7fff0000 }
- };
+ static uint32_t sOverdrawColors[2][4] = {{0x2f0000ff, 0x2f00ff00, 0x3fff0000, 0x7fff0000},
+ {0x2f0000ff, 0x4fffff00, 0x5fff8ad8, 0x7fff0000}};
if (amount < 1) amount = 1;
if (amount > 4) amount = 4;
@@ -160,46 +158,44 @@ void Caches::dumpMemoryUsage() {
ALOGD("%s", stringLog.string());
}
-void Caches::dumpMemoryUsage(String8 &log) {
+void Caches::dumpMemoryUsage(String8& log) {
uint32_t total = 0;
log.appendFormat("Current memory usage / total memory usage (bytes):\n");
- log.appendFormat(" TextureCache %8d / %8d\n",
- textureCache.getSize(), textureCache.getMaxSize());
+ log.appendFormat(" TextureCache %8d / %8d\n", textureCache.getSize(),
+ textureCache.getMaxSize());
if (mRenderState) {
int memused = 0;
for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
- it != mRenderState->mActiveLayers.end(); it++) {
+ it != mRenderState->mActiveLayers.end(); it++) {
const Layer* layer = *it;
LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL);
const GlLayer* glLayer = static_cast<const GlLayer*>(layer);
- log.appendFormat(" GlLayer size %dx%d; texid=%u refs=%d\n",
- layer->getWidth(), layer->getHeight(),
- glLayer->getTextureId(),
- layer->getStrongCount());
+ log.appendFormat(" GlLayer size %dx%d; texid=%u refs=%d\n", layer->getWidth(),
+ layer->getHeight(), glLayer->getTextureId(), layer->getStrongCount());
memused += layer->getWidth() * layer->getHeight() * 4;
}
- log.appendFormat(" Layers total %8d (numLayers = %zu)\n",
- memused, mRenderState->mActiveLayers.size());
+ log.appendFormat(" Layers total %8d (numLayers = %zu)\n", memused,
+ mRenderState->mActiveLayers.size());
total += memused;
}
- log.appendFormat(" RenderBufferCache %8d / %8d\n",
- renderBufferCache.getSize(), renderBufferCache.getMaxSize());
- log.appendFormat(" GradientCache %8d / %8d\n",
- gradientCache.getSize(), gradientCache.getMaxSize());
- log.appendFormat(" PathCache %8d / %8d\n",
- pathCache.getSize(), pathCache.getMaxSize());
- log.appendFormat(" TessellationCache %8d / %8d\n",
- tessellationCache.getSize(), tessellationCache.getMaxSize());
+ log.appendFormat(" RenderBufferCache %8d / %8d\n", renderBufferCache.getSize(),
+ renderBufferCache.getMaxSize());
+ log.appendFormat(" GradientCache %8d / %8d\n", gradientCache.getSize(),
+ gradientCache.getMaxSize());
+ log.appendFormat(" PathCache %8d / %8d\n", pathCache.getSize(),
+ pathCache.getMaxSize());
+ log.appendFormat(" TessellationCache %8d / %8d\n", tessellationCache.getSize(),
+ tessellationCache.getMaxSize());
log.appendFormat(" TextDropShadowCache %8d / %8d\n", dropShadowCache.getSize(),
- dropShadowCache.getMaxSize());
- log.appendFormat(" PatchCache %8d / %8d\n",
- patchCache.getSize(), patchCache.getMaxSize());
+ dropShadowCache.getMaxSize());
+ log.appendFormat(" PatchCache %8d / %8d\n", patchCache.getSize(),
+ patchCache.getMaxSize());
fontRenderer.dumpMemoryUsage(log);
log.appendFormat("Other:\n");
- log.appendFormat(" FboCache %8d / %8d\n",
- fboCache.getSize(), fboCache.getMaxSize());
+ log.appendFormat(" FboCache %8d / %8d\n", fboCache.getSize(),
+ fboCache.getMaxSize());
total += textureCache.getSize();
total += renderBufferCache.getSize();
@@ -238,13 +234,13 @@ void Caches::flush(FlushMode mode) {
gradientCache.clear();
fontRenderer.clear();
fboCache.clear();
- // fall through
+ // fall through
case FlushMode::Moderate:
fontRenderer.flush();
textureCache.flush();
pathCache.clear();
tessellationCache.clear();
- // fall through
+ // fall through
case FlushMode::Layers:
renderBufferCache.clear();
break;
@@ -274,5 +270,5 @@ TextureVertex* Caches::getRegionMesh() {
// Temporary Properties
///////////////////////////////////////////////////////////////////////////////
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 29eddde1e42b..97328324df04 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -22,20 +22,20 @@
#include "GammaFontRenderer.h"
#include "GradientCache.h"
#include "PatchCache.h"
-#include "ProgramCache.h"
#include "PathCache.h"
+#include "ProgramCache.h"
#include "RenderBufferCache.h"
-#include "renderstate/PixelBufferState.h"
-#include "renderstate/TextureState.h"
#include "ResourceCache.h"
#include "TessellationCache.h"
#include "TextDropShadowCache.h"
#include "TextureCache.h"
-#include "thread/TaskProcessor.h"
+#include "renderstate/PixelBufferState.h"
+#include "renderstate/TextureState.h"
#include "thread/TaskManager.h"
+#include "thread/TaskProcessor.h"
-#include <vector>
#include <memory>
+#include <vector>
#include <GLES3/gl3.h>
@@ -70,19 +70,14 @@ public:
return *sInstance;
}
- static bool hasInstance() {
- return sInstance != nullptr;
- }
+ static bool hasInstance() { return sInstance != nullptr; }
+
private:
explicit Caches(RenderState& renderState);
static Caches* sInstance;
public:
- enum class FlushMode {
- Layers = 0,
- Moderate,
- Full
- };
+ enum class FlushMode { Layers = 0, Moderate, Full };
/**
* Initialize caches.
@@ -181,9 +176,9 @@ private:
void initConstraints();
void initStaticProperties();
- static void eventMarkNull(GLsizei length, const GLchar* marker) { }
- static void startMarkNull(GLsizei length, const GLchar* marker) { }
- static void endMarkNull() { }
+ static void eventMarkNull(GLsizei length, const GLchar* marker) {}
+ static void startMarkNull(GLsizei length, const GLchar* marker) {}
+ static void endMarkNull() {}
RenderState* mRenderState;
@@ -198,9 +193,9 @@ private:
// TODO: move below to RenderState
PixelBufferState* mPixelBufferState = nullptr;
TextureState* mTextureState = nullptr;
- Program* mProgram = nullptr; // note: object owned by ProgramCache
+ Program* mProgram = nullptr; // note: object owned by ProgramCache
-}; // class Caches
+}; // class Caches
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/CanvasProperty.h b/libs/hwui/CanvasProperty.h
index 56671bba654b..fc76e8b68af8 100644
--- a/libs/hwui/CanvasProperty.h
+++ b/libs/hwui/CanvasProperty.h
@@ -27,6 +27,7 @@ namespace uirenderer {
class CanvasPropertyPrimitive : public VirtualLightRefBase {
PREVENT_COPY_AND_ASSIGN(CanvasPropertyPrimitive);
+
public:
explicit CanvasPropertyPrimitive(float initialValue) : value(initialValue) {}
@@ -35,6 +36,7 @@ public:
class CanvasPropertyPaint : public VirtualLightRefBase {
PREVENT_COPY_AND_ASSIGN(CanvasPropertyPaint);
+
public:
explicit CanvasPropertyPaint(const SkPaint& initialValue) : value(initialValue) {}
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index 9c068b080d45..d18c4abde7f2 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -21,14 +21,8 @@
namespace android {
namespace uirenderer {
-
CanvasState::CanvasState(CanvasStateClient& renderer)
- : mWidth(-1)
- , mHeight(-1)
- , mSaveCount(1)
- , mCanvas(renderer)
- , mSnapshot(&mFirstSnapshot) {
-}
+ : mWidth(-1), mHeight(-1), mSaveCount(1), mCanvas(renderer), mSnapshot(&mFirstSnapshot) {}
CanvasState::~CanvasState() {
// First call freeSnapshot on all but mFirstSnapshot
@@ -57,10 +51,9 @@ void CanvasState::initializeRecordingSaveStack(int viewportWidth, int viewportHe
mSaveCount = 1;
}
-void CanvasState::initializeSaveStack(
- int viewportWidth, int viewportHeight,
- float clipLeft, float clipTop,
- float clipRight, float clipBottom, const Vector3& lightCenter) {
+void CanvasState::initializeSaveStack(int viewportWidth, int viewportHeight, float clipLeft,
+ float clipTop, float clipRight, float clipBottom,
+ const Vector3& lightCenter) {
if (mWidth != viewportWidth || mHeight != viewportHeight) {
mWidth = viewportWidth;
mHeight = viewportHeight;
@@ -92,7 +85,7 @@ void CanvasState::freeSnapshot(Snapshot* snapshot) {
snapshot->~Snapshot();
// Arbitrary number, just don't let this grown unbounded
if (mSnapshotPoolCount > 10) {
- free((void*) snapshot);
+ free((void*)snapshot);
} else {
snapshot->previous = mSnapshotPool;
mSnapshotPool = snapshot;
@@ -215,7 +208,7 @@ bool CanvasState::clipPath(const SkPath* path, SkClipOp op) {
void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
Rect bounds;
float radius;
- if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
+ if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
bool outlineIsRounded = MathUtils::isPositive(radius);
if (!outlineIsRounded || currentTransform()->isSimple()) {
@@ -241,10 +234,9 @@ void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline*
* @param snapOut if set, the geometry will be treated as having an AA ramp.
* See Rect::snapGeometryToPixelBoundaries()
*/
-bool CanvasState::calculateQuickRejectForScissor(float left, float top,
- float right, float bottom,
- bool* clipRequired, bool* roundRectClipRequired,
- bool snapOut) const {
+bool CanvasState::calculateQuickRejectForScissor(float left, float top, float right, float bottom,
+ bool* clipRequired, bool* roundRectClipRequired,
+ bool snapOut) const {
if (bottom <= top || right <= left) {
return true;
}
@@ -265,21 +257,20 @@ bool CanvasState::calculateQuickRejectForScissor(float left, float top,
// round rect clip is required if RR clip exists, and geometry intersects its corners
if (roundRectClipRequired) {
- *roundRectClipRequired = mSnapshot->roundRectClipState != nullptr
- && mSnapshot->roundRectClipState->areaRequiresRoundRectClip(r);
+ *roundRectClipRequired = mSnapshot->roundRectClipState != nullptr &&
+ mSnapshot->roundRectClipState->areaRequiresRoundRectClip(r);
}
return false;
}
-bool CanvasState::quickRejectConservative(float left, float top,
- float right, float bottom) const {
+bool CanvasState::quickRejectConservative(float left, float top, float right, float bottom) const {
if (bottom <= top || right <= left) {
return true;
}
Rect r(left, top, right, bottom);
currentTransform()->mapRect(r);
- r.roundOut(); // rounded out to be conservative
+ r.roundOut(); // rounded out to be conservative
Rect clipRect(currentRenderTargetClip());
clipRect.snapToPixelBoundaries();
@@ -289,5 +280,5 @@ bool CanvasState::quickRejectConservative(float left, float top,
return false;
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h
index b1fe09eb1aec..9ac35ff47dab 100644
--- a/libs/hwui/CanvasState.h
+++ b/libs/hwui/CanvasState.h
@@ -32,8 +32,8 @@ namespace uirenderer {
*/
class CanvasStateClient {
public:
- CanvasStateClient() { }
- virtual ~CanvasStateClient() { }
+ CanvasStateClient() {}
+ virtual ~CanvasStateClient() {}
/**
* Callback allowing embedder to take actions in the middle of a
@@ -53,7 +53,7 @@ public:
*/
virtual GLuint getTargetFbo() const = 0;
-}; // class CanvasStateClient
+}; // class CanvasStateClient
/**
* Implements Canvas state methods on behalf of Renderers.
@@ -86,13 +86,10 @@ public:
* Initializes the first snapshot, computing the projection matrix,
* and stores the dimensions of the render target.
*/
- void initializeSaveStack(int viewportWidth, int viewportHeight,
- float clipLeft, float clipTop, float clipRight, float clipBottom,
- const Vector3& lightCenter);
+ void initializeSaveStack(int viewportWidth, int viewportHeight, float clipLeft, float clipTop,
+ float clipRight, float clipBottom, const Vector3& lightCenter);
- bool hasRectToRectTransform() const {
- return CC_LIKELY(currentTransform()->rectToRect());
- }
+ bool hasRectToRectTransform() const { return CC_LIKELY(currentTransform()->rectToRect()); }
// Save (layer)
int getSaveCount() const { return mSaveCount; }
@@ -112,9 +109,9 @@ public:
void skew(float sx, float sy);
void setMatrix(const SkMatrix& matrix);
- void setMatrix(const Matrix4& matrix); // internal only convenience method
+ void setMatrix(const Matrix4& matrix); // internal only convenience method
void concatMatrix(const SkMatrix& matrix);
- void concatMatrix(const Matrix4& matrix); // internal only convenience method
+ void concatMatrix(const Matrix4& matrix); // internal only convenience method
// Clip
const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
@@ -132,13 +129,11 @@ public:
* outline.
*/
void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
- void setClippingRoundRect(LinearAllocator& allocator,
- const Rect& rect, float radius, bool highPriority = true) {
+ void setClippingRoundRect(LinearAllocator& allocator, const Rect& rect, float radius,
+ bool highPriority = true) {
mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
}
- void setProjectionPathMask(const SkPath* path) {
- mSnapshot->setProjectionPathMask(path);
- }
+ void setProjectionPathMask(const SkPath* path) { mSnapshot->setProjectionPathMask(path); }
/**
* Returns true if drawing in the rectangle (left, top, right, bottom)
@@ -146,14 +141,19 @@ public:
* perfect tests would return true.
*/
bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
- bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
+ bool* clipRequired, bool* roundRectClipRequired,
+ bool snapOut) const;
void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
- inline const Rect& currentRenderTargetClip() const { return currentSnapshot()->getRenderTargetClip(); }
+ inline const Rect& currentRenderTargetClip() const {
+ return currentSnapshot()->getRenderTargetClip();
+ }
inline int currentFlags() const { return currentSnapshot()->flags; }
- const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
+ const Vector3& currentLightCenter() const {
+ return currentSnapshot()->getRelativeLightCenter();
+ }
int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
int getWidth() const { return mWidth; }
@@ -189,7 +189,7 @@ private:
Snapshot* mSnapshotPool = nullptr;
int mSnapshotPoolCount = 0;
-}; // class CanvasState
+}; // class CanvasState
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index 84451bacbc09..27d93cfa0391 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -33,7 +33,7 @@ static void handlePoint(Rect& transformedBounds, const Matrix4& transform, float
Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform) {
const float kMinFloat = std::numeric_limits<float>::lowest();
const float kMaxFloat = std::numeric_limits<float>::max();
- Rect transformedBounds = { kMaxFloat, kMaxFloat, kMinFloat, kMinFloat };
+ Rect transformedBounds = {kMaxFloat, kMaxFloat, kMinFloat, kMinFloat};
handlePoint(transformedBounds, transform, r.left, r.top);
handlePoint(transformedBounds, transform, r.right, r.top);
handlePoint(transformedBounds, transform, r.left, r.bottom);
@@ -49,18 +49,12 @@ void ClipBase::dump() const {
* TransformedRectangle
*/
-TransformedRectangle::TransformedRectangle() {
-}
-
-TransformedRectangle::TransformedRectangle(const Rect& bounds,
- const Matrix4& transform)
- : mBounds(bounds)
- , mTransform(transform) {
-}
+TransformedRectangle::TransformedRectangle() {}
-bool TransformedRectangle::canSimplyIntersectWith(
- const TransformedRectangle& other) const {
+TransformedRectangle::TransformedRectangle(const Rect& bounds, const Matrix4& transform)
+ : mBounds(bounds), mTransform(transform) {}
+bool TransformedRectangle::canSimplyIntersectWith(const TransformedRectangle& other) const {
return mTransform == other.mTransform;
}
@@ -76,9 +70,7 @@ bool TransformedRectangle::isEmpty() const {
* RectangleList
*/
-RectangleList::RectangleList()
- : mTransformedRectanglesCount(0) {
-}
+RectangleList::RectangleList() : mTransformedRectanglesCount(0) {}
bool RectangleList::isEmpty() const {
if (mTransformedRectanglesCount < 1) {
@@ -110,8 +102,7 @@ void RectangleList::set(const Rect& bounds, const Matrix4& transform) {
mTransformedRectangles[0] = TransformedRectangle(bounds, transform);
}
-bool RectangleList::intersectWith(const Rect& bounds,
- const Matrix4& transform) {
+bool RectangleList::intersectWith(const Rect& bounds, const Matrix4& transform) {
TransformedRectangle newRectangle(bounds, transform);
// Try to find a rectangle with a compatible transformation
@@ -148,8 +139,7 @@ Rect RectangleList::calculateBounds() const {
return bounds;
}
-static SkPath pathFromTransformedRectangle(const Rect& bounds,
- const Matrix4& transform) {
+static SkPath pathFromTransformedRectangle(const Rect& bounds, const Matrix4& transform) {
SkPath rectPath;
SkPath rectPathTransformed;
rectPath.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom);
@@ -163,8 +153,8 @@ SkRegion RectangleList::convertToRegion(const SkRegion& clip) const {
SkRegion rectangleListAsRegion;
for (int index = 0; index < mTransformedRectanglesCount; index++) {
const TransformedRectangle& tr(mTransformedRectangles[index]);
- SkPath rectPathTransformed = pathFromTransformedRectangle(
- tr.getBounds(), tr.getTransform());
+ SkPath rectPathTransformed =
+ pathFromTransformedRectangle(tr.getBounds(), tr.getTransform());
if (index == 0) {
rectangleListAsRegion.setPath(rectPathTransformed, clip);
} else {
@@ -186,9 +176,7 @@ void RectangleList::transform(const Matrix4& transform) {
* ClipArea
*/
-ClipArea::ClipArea()
- : mMode(ClipMode::Rectangle) {
-}
+ClipArea::ClipArea() : mMode(ClipMode::Rectangle) {}
/*
* Interface
@@ -215,21 +203,20 @@ void ClipArea::setClip(float left, float top, float right, float bottom) {
mClipRegion.setEmpty();
}
-void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
- SkRegion::Op op) {
+void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op) {
if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
onClipUpdated();
switch (mMode) {
- case ClipMode::Rectangle:
- rectangleModeClipRectWithTransform(r, transform, op);
- break;
- case ClipMode::RectangleList:
- rectangleListModeClipRectWithTransform(r, transform, op);
- break;
- case ClipMode::Region:
- regionModeClipRectWithTransform(r, transform, op);
- break;
+ case ClipMode::Rectangle:
+ rectangleModeClipRectWithTransform(r, transform, op);
+ break;
+ case ClipMode::RectangleList:
+ rectangleListModeClipRectWithTransform(r, transform, op);
+ break;
+ case ClipMode::Region:
+ regionModeClipRectWithTransform(r, transform, op);
+ break;
}
}
@@ -242,8 +229,7 @@ void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
onClipRegionUpdated();
}
-void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
- SkRegion::Op op) {
+void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op) {
if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
onClipUpdated();
@@ -269,9 +255,8 @@ void ClipArea::enterRectangleMode() {
mMode = ClipMode::Rectangle;
}
-void ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
- const mat4* transform, SkRegion::Op op) {
-
+void ClipArea::rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform,
+ SkRegion::Op op) {
if (op == SkRegion::kReplace_Op && transform->rectToRect()) {
mClipRect = r;
transform->mapRect(mClipRect);
@@ -306,10 +291,9 @@ void ClipArea::enterRectangleListMode() {
mRectangleList.set(mClipRect, Matrix4::identity());
}
-void ClipArea::rectangleListModeClipRectWithTransform(const Rect& r,
- const mat4* transform, SkRegion::Op op) {
- if (op != SkRegion::kIntersect_Op
- || !mRectangleList.intersectWith(r, *transform)) {
+void ClipArea::rectangleListModeClipRectWithTransform(const Rect& r, const mat4* transform,
+ SkRegion::Op op) {
+ if (op != SkRegion::kIntersect_Op || !mRectangleList.intersectWith(r, *transform)) {
enterRegionMode();
regionModeClipRectWithTransform(r, transform, op);
}
@@ -332,8 +316,8 @@ void ClipArea::enterRegionMode() {
}
}
-void ClipArea::regionModeClipRectWithTransform(const Rect& r,
- const mat4* transform, SkRegion::Op op) {
+void ClipArea::regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
+ SkRegion::Op op) {
SkPath transformedRect = pathFromTransformedRectangle(r, *transform);
SkRegion transformedRectRegion;
regionFromPath(transformedRect, transformedRectRegion);
@@ -365,24 +349,24 @@ const ClipBase* ClipArea::serializeClip(LinearAllocator& allocator) {
}
static_assert(std::is_trivially_destructible<Rect>::value,
- "expect Rect to be trivially destructible");
+ "expect Rect to be trivially destructible");
static_assert(std::is_trivially_destructible<RectangleList>::value,
- "expect RectangleList to be trivially destructible");
+ "expect RectangleList to be trivially destructible");
if (mLastSerialization == nullptr) {
ClipBase* serialization = nullptr;
switch (mMode) {
- case ClipMode::Rectangle:
- serialization = allocator.create<ClipRect>(mClipRect);
- break;
- case ClipMode::RectangleList:
- serialization = allocator.create<ClipRectList>(mRectangleList);
- serialization->rect = mRectangleList.calculateBounds();
- break;
- case ClipMode::Region:
- serialization = allocator.create<ClipRegion>(mClipRegion);
- serialization->rect.set(mClipRegion.getBounds());
- break;
+ case ClipMode::Rectangle:
+ serialization = allocator.create<ClipRect>(mClipRect);
+ break;
+ case ClipMode::RectangleList:
+ serialization = allocator.create<ClipRectList>(mRectangleList);
+ serialization->rect = mRectangleList.calculateBounds();
+ break;
+ case ClipMode::Region:
+ serialization = allocator.create<ClipRegion>(mClipRegion);
+ serialization->rect.set(mClipRegion.getBounds());
+ break;
}
serialization->intersectWithRoot = mReplaceOpObserved;
// TODO: this is only done for draw time, should eventually avoid for record time
@@ -404,81 +388,79 @@ inline static const SkRegion& getRegion(const ClipBase* scb) {
// For simplicity, doesn't account for rect merging
static bool cannotFitInRectangleList(const ClipArea& clipArea, const ClipBase* scb) {
int currentRectCount = clipArea.isRectangleList()
- ? clipArea.getRectangleList().getTransformedRectanglesCount()
- : 1;
+ ? clipArea.getRectangleList().getTransformedRectanglesCount()
+ : 1;
int recordedRectCount = (scb->mode == ClipMode::RectangleList)
- ? getRectList(scb).getTransformedRectanglesCount()
- : 1;
+ ? getRectList(scb).getTransformedRectanglesCount()
+ : 1;
return currentRectCount + recordedRectCount > RectangleList::kMaxTransformedRectangles;
}
static const ClipRect sEmptyClipRect(Rect(0, 0));
const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator,
- const ClipBase* recordedClip, const Matrix4& recordedClipTransform) {
-
+ const ClipBase* recordedClip,
+ const Matrix4& recordedClipTransform) {
// if no recordedClip passed, just serialize current state
if (!recordedClip) return serializeClip(allocator);
// if either is empty, clip is empty
- if (CC_UNLIKELY(recordedClip->rect.isEmpty())|| mClipRect.isEmpty()) return &sEmptyClipRect;
+ if (CC_UNLIKELY(recordedClip->rect.isEmpty()) || mClipRect.isEmpty()) return &sEmptyClipRect;
- if (!mLastResolutionResult
- || recordedClip != mLastResolutionClip
- || recordedClipTransform != mLastResolutionTransform) {
+ if (!mLastResolutionResult || recordedClip != mLastResolutionClip ||
+ recordedClipTransform != mLastResolutionTransform) {
mLastResolutionClip = recordedClip;
mLastResolutionTransform = recordedClipTransform;
- if (CC_LIKELY(mMode == ClipMode::Rectangle
- && recordedClip->mode == ClipMode::Rectangle
- && recordedClipTransform.rectToRect())) {
+ if (CC_LIKELY(mMode == ClipMode::Rectangle && recordedClip->mode == ClipMode::Rectangle &&
+ recordedClipTransform.rectToRect())) {
// common case - result is a single rectangle
auto rectClip = allocator.create<ClipRect>(recordedClip->rect);
recordedClipTransform.mapRect(rectClip->rect);
rectClip->rect.doIntersect(mClipRect);
rectClip->rect.snapToPixelBoundaries();
mLastResolutionResult = rectClip;
- } else if (CC_UNLIKELY(mMode == ClipMode::Region
- || recordedClip->mode == ClipMode::Region
- || cannotFitInRectangleList(*this, recordedClip))) {
+ } else if (CC_UNLIKELY(mMode == ClipMode::Region ||
+ recordedClip->mode == ClipMode::Region ||
+ cannotFitInRectangleList(*this, recordedClip))) {
// region case
SkRegion other;
switch (recordedClip->mode) {
- case ClipMode::Rectangle:
- if (CC_LIKELY(recordedClipTransform.rectToRect())) {
- // simple transform, skip creating SkPath
- Rect resultClip(recordedClip->rect);
- recordedClipTransform.mapRect(resultClip);
- other.setRect(resultClip.toSkIRect());
- } else {
- SkPath transformedRect = pathFromTransformedRectangle(recordedClip->rect,
- recordedClipTransform);
- other.setPath(transformedRect, createViewportRegion());
+ case ClipMode::Rectangle:
+ if (CC_LIKELY(recordedClipTransform.rectToRect())) {
+ // simple transform, skip creating SkPath
+ Rect resultClip(recordedClip->rect);
+ recordedClipTransform.mapRect(resultClip);
+ other.setRect(resultClip.toSkIRect());
+ } else {
+ SkPath transformedRect = pathFromTransformedRectangle(
+ recordedClip->rect, recordedClipTransform);
+ other.setPath(transformedRect, createViewportRegion());
+ }
+ break;
+ case ClipMode::RectangleList: {
+ RectangleList transformedList(getRectList(recordedClip));
+ transformedList.transform(recordedClipTransform);
+ other = transformedList.convertToRegion(createViewportRegion());
+ break;
}
- break;
- case ClipMode::RectangleList: {
- RectangleList transformedList(getRectList(recordedClip));
- transformedList.transform(recordedClipTransform);
- other = transformedList.convertToRegion(createViewportRegion());
- break;
- }
- case ClipMode::Region:
- other = getRegion(recordedClip);
- applyTransformToRegion(recordedClipTransform, &other);
+ case ClipMode::Region:
+ other = getRegion(recordedClip);
+ applyTransformToRegion(recordedClipTransform, &other);
}
ClipRegion* regionClip = allocator.create<ClipRegion>();
switch (mMode) {
- case ClipMode::Rectangle:
- regionClip->region.op(mClipRect.toSkIRect(), other, SkRegion::kIntersect_Op);
- break;
- case ClipMode::RectangleList:
- regionClip->region.op(mRectangleList.convertToRegion(createViewportRegion()),
- other, SkRegion::kIntersect_Op);
- break;
- case ClipMode::Region:
- regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op);
- break;
+ case ClipMode::Rectangle:
+ regionClip->region.op(mClipRect.toSkIRect(), other, SkRegion::kIntersect_Op);
+ break;
+ case ClipMode::RectangleList:
+ regionClip->region.op(mRectangleList.convertToRegion(createViewportRegion()),
+ other, SkRegion::kIntersect_Op);
+ break;
+ case ClipMode::Region:
+ regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op);
+ break;
}
// Don't need to snap, since region's in int bounds
regionClip->rect.set(regionClip->region.getBounds());
@@ -510,7 +492,7 @@ const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator,
}
void ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) {
- if (!clip) return; // nothing to do
+ if (!clip) return; // nothing to do
if (CC_LIKELY(clip->mode == ClipMode::Rectangle)) {
clipRectWithTransform(clip->rect, &transform, SkRegion::kIntersect_Op);
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index cf5751606d12..a7a11801cfe2 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -39,18 +39,14 @@ public:
bool isEmpty() const;
- const Rect& getBounds() const {
- return mBounds;
- }
+ const Rect& getBounds() const { return mBounds; }
Rect transformedBounds() const {
Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
return transformedBounds;
}
- const Matrix4& getTransform() const {
- return mTransform;
- }
+ const Matrix4& getTransform() const { return mTransform; }
void transform(const Matrix4& transform) {
Matrix4 t;
@@ -79,9 +75,7 @@ public:
SkRegion convertToRegion(const SkRegion& clip) const;
Rect calculateBounds() const;
- enum {
- kMaxTransformedRectangles = 5
- };
+ enum { kMaxTransformedRectangles = 5 };
private:
int mTransformedRectanglesCount;
@@ -97,11 +91,8 @@ enum class ClipMode {
};
struct ClipBase {
- explicit ClipBase(ClipMode mode)
- : mode(mode) {}
- explicit ClipBase(const Rect& rect)
- : mode(ClipMode::Rectangle)
- , rect(rect) {}
+ explicit ClipBase(ClipMode mode) : mode(mode) {}
+ explicit ClipBase(const Rect& rect) : mode(ClipMode::Rectangle), rect(rect) {}
const ClipMode mode;
bool intersectWithRoot = false;
// Bounds of the clipping area, used to define the scissor, and define which
@@ -112,23 +103,18 @@ struct ClipBase {
};
struct ClipRect : ClipBase {
- explicit ClipRect(const Rect& rect)
- : ClipBase(rect) {}
+ explicit ClipRect(const Rect& rect) : ClipBase(rect) {}
};
struct ClipRectList : ClipBase {
explicit ClipRectList(const RectangleList& rectList)
- : ClipBase(ClipMode::RectangleList)
- , rectList(rectList) {}
+ : ClipBase(ClipMode::RectangleList), rectList(rectList) {}
RectangleList rectList;
};
struct ClipRegion : ClipBase {
- explicit ClipRegion(const SkRegion& region)
- : ClipBase(ClipMode::Region)
- , region(region) {}
- ClipRegion()
- : ClipBase(ClipMode::Region) {}
+ explicit ClipRegion(const SkRegion& region) : ClipBase(ClipMode::Region), region(region) {}
+ ClipRegion() : ClipBase(ClipMode::Region) {}
SkRegion region;
};
@@ -138,44 +124,29 @@ public:
void setViewportDimensions(int width, int height);
- bool isEmpty() const {
- return mClipRect.isEmpty();
- }
+ bool isEmpty() const { return mClipRect.isEmpty(); }
void setEmpty();
void setClip(float left, float top, float right, float bottom);
- void clipRectWithTransform(const Rect& r, const mat4* transform,
- SkRegion::Op op);
- void clipPathWithTransform(const SkPath& path, const mat4* transform,
- SkRegion::Op op);
+ void clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
+ void clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op);
- const Rect& getClipRect() const {
- return mClipRect;
- }
+ const Rect& getClipRect() const { return mClipRect; }
- const SkRegion& getClipRegion() const {
- return mClipRegion;
- }
+ const SkRegion& getClipRegion() const { return mClipRegion; }
- const RectangleList& getRectangleList() const {
- return mRectangleList;
- }
+ const RectangleList& getRectangleList() const { return mRectangleList; }
- bool isRegion() const {
- return ClipMode::Region == mMode;
- }
+ bool isRegion() const { return ClipMode::Region == mMode; }
- bool isSimple() const {
- return mMode == ClipMode::Rectangle;
- }
+ bool isSimple() const { return mMode == ClipMode::Rectangle; }
- bool isRectangleList() const {
- return mMode == ClipMode::RectangleList;
- }
+ bool isRectangleList() const { return mMode == ClipMode::RectangleList; }
WARN_UNUSED_RESULT const ClipBase* serializeClip(LinearAllocator& allocator);
- WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
- const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
+ WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(
+ LinearAllocator& allocator, const ClipBase* recordedClip,
+ const Matrix4& recordedClipTransform);
void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
static void applyTransformToRegion(const Matrix4& transform, SkRegion* region);
@@ -185,14 +156,13 @@ private:
void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
void enterRectangleListMode();
- void rectangleListModeClipRectWithTransform(const Rect& r,
- const mat4* transform, SkRegion::Op op);
+ void rectangleListModeClipRectWithTransform(const Rect& r, const mat4* transform,
+ SkRegion::Op op);
void enterRegionModeFromRectangleMode();
void enterRegionModeFromRectangleListMode();
void enterRegionMode();
- void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
- SkRegion::Op op);
+ void regionModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
void clipRegion(const SkRegion& region, SkRegion::Op op);
void ensureClipRegion();
@@ -205,9 +175,7 @@ private:
mLastResolutionResult = nullptr;
}
- SkRegion createViewportRegion() {
- return SkRegion(mViewportBounds.toSkIRect());
- }
+ SkRegion createViewportRegion() { return SkRegion(mViewportBounds.toSkIRect()); }
void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
// TODO: this should not mask every path to the viewport - this makes it impossible to use
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 2b4fe17d424d..cca0032b230e 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -57,17 +57,18 @@ static void computeTransformImpl(const DirtyStack* currentFrame, Matrix4* outMat
computeTransformImpl(currentFrame->prev, outMatrix);
}
switch (currentFrame->type) {
- case TransformRenderNode:
- currentFrame->renderNode->applyViewPropertyTransforms(*outMatrix);
- break;
- case TransformMatrix4:
- outMatrix->multiply(*currentFrame->matrix4);
- break;
- case TransformNone:
- // nothing to be done
- break;
- default:
- LOG_ALWAYS_FATAL("Tried to compute transform with an invalid type: %d", currentFrame->type);
+ case TransformRenderNode:
+ currentFrame->renderNode->applyViewPropertyTransforms(*outMatrix);
+ break;
+ case TransformMatrix4:
+ outMatrix->multiply(*currentFrame->matrix4);
+ break;
+ case TransformNone:
+ // nothing to be done
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Tried to compute transform with an invalid type: %d",
+ currentFrame->type);
}
}
@@ -104,17 +105,17 @@ void DamageAccumulator::popTransform() {
DirtyStack* dirtyFrame = mHead;
mHead = mHead->prev;
switch (dirtyFrame->type) {
- case TransformRenderNode:
- applyRenderNodeTransform(dirtyFrame);
- break;
- case TransformMatrix4:
- applyMatrix4Transform(dirtyFrame);
- break;
- case TransformNone:
- mHead->pendingDirty.join(dirtyFrame->pendingDirty);
- break;
- default:
- LOG_ALWAYS_FATAL("Tried to pop an invalid type: %d", dirtyFrame->type);
+ case TransformRenderNode:
+ applyRenderNodeTransform(dirtyFrame);
+ break;
+ case TransformMatrix4:
+ applyMatrix4Transform(dirtyFrame);
+ break;
+ case TransformNone:
+ mHead->pendingDirty.join(dirtyFrame->pendingDirty);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Tried to pop an invalid type: %d", dirtyFrame->type);
}
}
@@ -168,8 +169,7 @@ static DirtyStack* findProjectionReceiver(DirtyStack* frame) {
if (frame) {
while (frame->prev != frame) {
frame = frame->prev;
- if (frame->type == TransformRenderNode
- && frame->renderNode->hasProjectionReceiver()) {
+ if (frame->type == TransformRenderNode && frame->renderNode->hasProjectionReceiver()) {
return frame;
}
}
@@ -233,7 +233,8 @@ void DamageAccumulator::peekAtDirty(SkRect* dest) const {
}
void DamageAccumulator::finish(SkRect* totalDirty) {
- LOG_ALWAYS_FATAL_IF(mHead->prev != mHead, "Cannot finish, mismatched push/pop calls! %p vs. %p", mHead->prev, mHead);
+ LOG_ALWAYS_FATAL_IF(mHead->prev != mHead, "Cannot finish, mismatched push/pop calls! %p vs. %p",
+ mHead->prev, mHead);
// Root node never has a transform, so this is the fully mapped dirty rect
*totalDirty = mHead->pendingDirty;
totalDirty->roundOut(totalDirty);
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index 250296ecc89f..7d0b6877a71a 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -26,7 +26,7 @@
// Smaller than INT_MIN/INT_MAX because we offset these values
// and thus don't want to be adding offsets to INT_MAX, that's bad
-#define DIRTY_MIN (-0x7ffffff-1)
+#define DIRTY_MIN (-0x7ffffff - 1)
#define DIRTY_MAX (0x7ffffff)
namespace android {
@@ -38,6 +38,7 @@ class Matrix4;
class DamageAccumulator {
PREVENT_COPY_AND_ASSIGN(DamageAccumulator);
+
public:
DamageAccumulator();
// mAllocator will clean everything up for us, no need for a dtor
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index e29699d0faf4..9b1ba69a5377 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -102,9 +102,9 @@
#define DEBUG_VECTOR_DRAWABLE 0
#if DEBUG_INIT
- #define INIT_LOGD(...) ALOGD(__VA_ARGS__)
+#define INIT_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define INIT_LOGD(...)
+#define INIT_LOGD(...)
#endif
-#endif // ANDROID_HWUI_DEBUG_H
+#endif // ANDROID_HWUI_DEBUG_H
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index ff90160b8855..569de76f294e 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -26,7 +26,7 @@ namespace android {
namespace uirenderer {
DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
- Layer::Api layerApi)
+ Layer::Api layerApi)
: mRenderState(renderState)
, mBlend(false)
, mSurfaceTexture(nullptr)
@@ -40,7 +40,6 @@ DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState, CreateLayer
}
DeferredLayerUpdater::~DeferredLayerUpdater() {
- SkSafeUnref(mColorFilter);
setTransform(nullptr);
mRenderState.unregisterDeferredLayerUpdater(this);
destroyLayer();
@@ -67,8 +66,11 @@ void DeferredLayerUpdater::destroyLayer() {
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
mAlpha = PaintUtils::getAlphaDirect(paint);
mMode = PaintUtils::getBlendModeDirect(paint);
- SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : nullptr;
- SkRefCnt_SafeAssign(mColorFilter, colorFilter);
+ if (paint) {
+ mColorFilter = paint->refColorFilter();
+ } else {
+ mColorFilter.reset();
+ }
}
void DeferredLayerUpdater::apply() {
@@ -110,8 +112,8 @@ void DeferredLayerUpdater::apply() {
void DeferredLayerUpdater::doUpdateTexImage() {
LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
- "doUpdateTexImage non GL backend %x, GL %x, VK %x",
- mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
+ "doUpdateTexImage non GL backend %x, GL %x, VK %x", mLayer->getApi(),
+ Layer::Api::OpenGL, Layer::Api::Vulkan);
if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
float transform[16];
@@ -132,38 +134,40 @@ void DeferredLayerUpdater::doUpdateTexImage() {
sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
if (buffer != nullptr) {
// force filtration if buffer size != layer size
- forceFilter = mWidth != static_cast<int>(buffer->getWidth())
- || mHeight != static_cast<int>(buffer->getHeight());
+ forceFilter = mWidth != static_cast<int>(buffer->getWidth()) ||
+ mHeight != static_cast<int>(buffer->getHeight());
}
- #if DEBUG_RENDERER
+#if DEBUG_RENDERER
if (dropCounter > 0) {
RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
}
- #endif
+#endif
mSurfaceTexture->getTransformMatrix(transform);
- updateLayer(forceFilter, transform);
+ updateLayer(forceFilter, transform, mSurfaceTexture->getCurrentDataSpace());
}
}
void DeferredLayerUpdater::doUpdateVkTexImage() {
LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::Vulkan,
- "updateLayer non Vulkan backend %x, GL %x, VK %x",
- mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
+ "updateLayer non Vulkan backend %x, GL %x, VK %x", mLayer->getApi(),
+ Layer::Api::OpenGL, Layer::Api::Vulkan);
static const mat4 identityMatrix;
- updateLayer(false, identityMatrix.data);
+ updateLayer(false, identityMatrix.data, HAL_DATASPACE_UNKNOWN);
VkLayer* vkLayer = static_cast<VkLayer*>(mLayer);
vkLayer->updateTexture();
}
-void DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform) {
+void DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform,
+ android_dataspace dataspace) {
mLayer->setBlend(mBlend);
mLayer->setForceFilter(forceFilter);
mLayer->setSize(mWidth, mHeight);
mLayer->getTexTransform().load(textureTransform);
+ mLayer->setDataSpace(dataspace);
}
void DeferredLayerUpdater::detachSurfaceTexture() {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 6164e4744da5..fe3ee7a2b4c6 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -16,10 +16,11 @@
#pragma once
-#include <cutils/compiler.h>
-#include <gui/GLConsumer.h>
#include <SkColorFilter.h>
#include <SkMatrix.h>
+#include <cutils/compiler.h>
+#include <gui/GLConsumer.h>
+#include <system/graphics.h>
#include <utils/StrongPointer.h>
#include <GLES2/gl2.h>
@@ -41,10 +42,11 @@ public:
// Note that DeferredLayerUpdater assumes it is taking ownership of the layer
// and will not call incrementRef on it as a result.
typedef std::function<Layer*(RenderState& renderState, uint32_t layerWidth,
- uint32_t layerHeight, SkColorFilter* colorFilter, int alpha,
- SkBlendMode mode, bool blend)> CreateLayerFn;
- ANDROID_API explicit DeferredLayerUpdater(RenderState& renderState,
- CreateLayerFn createLayerFn, Layer::Api layerApi);
+ uint32_t layerHeight, sk_sp<SkColorFilter> colorFilter, int alpha,
+ SkBlendMode mode, bool blend)>
+ CreateLayerFn;
+ ANDROID_API explicit DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
+ Layer::Api layerApi);
ANDROID_API ~DeferredLayerUpdater();
@@ -74,40 +76,32 @@ public:
GLenum target = texture->getCurrentTextureTarget();
LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
- "set unsupported GLConsumer with target %x", target);
+ "set unsupported GLConsumer with target %x", target);
}
}
- ANDROID_API void updateTexImage() {
- mUpdateTexImage = true;
- }
+ ANDROID_API void updateTexImage() { mUpdateTexImage = true; }
ANDROID_API void setTransform(const SkMatrix* matrix) {
delete mTransform;
mTransform = matrix ? new SkMatrix(*matrix) : nullptr;
}
- SkMatrix* getTransform() {
- return mTransform;
- }
+ SkMatrix* getTransform() { return mTransform; }
ANDROID_API void setPaint(const SkPaint* paint);
void apply();
- Layer* backingLayer() {
- return mLayer;
- }
+ Layer* backingLayer() { return mLayer; }
void detachSurfaceTexture();
- void updateLayer(bool forceFilter, const float* textureTransform);
+ void updateLayer(bool forceFilter, const float* textureTransform, android_dataspace dataspace);
void destroyLayer();
- Layer::Api getBackingLayerApi() {
- return mLayerApi;
- }
+ Layer::Api getBackingLayerApi() { return mLayerApi; }
private:
RenderState& mRenderState;
@@ -116,7 +110,7 @@ private:
int mWidth = 0;
int mHeight = 0;
bool mBlend = false;
- SkColorFilter* mColorFilter = nullptr;
+ sk_sp<SkColorFilter> mColorFilter;
int mAlpha = 255;
SkBlendMode mMode = SkBlendMode::kSrcOver;
sp<GLConsumer> mSurfaceTexture;
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 37965daf9a8d..40cc73a82846 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -16,11 +16,13 @@
#include <DeviceInfo.h>
+#include "Properties.h"
+
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <thread>
#include <mutex>
+#include <thread>
#include <log/log.h>
@@ -29,6 +31,19 @@
namespace android {
namespace uirenderer {
+static constexpr android::DisplayInfo sDummyDisplay {
+ 1080, // w
+ 1920, // h
+ 320.0, // xdpi
+ 320.0, // ydpi
+ 60.0, // fps
+ 2.0, // density
+ 0, // orientation
+ false, // secure?
+ 0, // appVsyncOffset
+ 0, // presentationDeadline
+};
+
static DeviceInfo* sDeviceInfo = nullptr;
static std::once_flag sInitializedFlag;
@@ -47,21 +62,26 @@ void DeviceInfo::initialize() {
void DeviceInfo::initialize(int maxTextureSize) {
std::call_once(sInitializedFlag, [maxTextureSize]() {
sDeviceInfo = new DeviceInfo();
- sDeviceInfo->loadDisplayInfo();
+ sDeviceInfo->mDisplayInfo = DeviceInfo::queryDisplayInfo();
sDeviceInfo->mMaxTextureSize = maxTextureSize;
});
}
void DeviceInfo::load() {
- loadDisplayInfo();
+ mDisplayInfo = queryDisplayInfo();
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
}
-void DeviceInfo::loadDisplayInfo() {
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
+DisplayInfo DeviceInfo::queryDisplayInfo() {
+ if (Properties::isolatedProcess) {
+ return sDummyDisplay;
+ }
+
+ DisplayInfo displayInfo;
+ sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &displayInfo);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display info, error %d", status);
+ return displayInfo;
}
} /* namespace uirenderer */
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 5bd7b14b156d..297b2664414b 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -18,14 +18,15 @@
#include <ui/DisplayInfo.h>
-#include "utils/Macros.h"
#include "Extensions.h"
+#include "utils/Macros.h"
namespace android {
namespace uirenderer {
class DeviceInfo {
PREVENT_COPY_AND_ASSIGN(DeviceInfo);
+
public:
// returns nullptr if DeviceInfo is not initialized yet
// Note this does not have a memory fence so it's up to the caller
@@ -46,12 +47,13 @@ public:
return di.w * di.h * in;
}
+ static DisplayInfo queryDisplayInfo();
+
private:
DeviceInfo() {}
~DeviceInfo() {}
void load();
- void loadDisplayInfo();
int mMaxTextureSize;
DisplayInfo mDisplayInfo;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 0ff101c6b2b4..aa87aea8b374 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -44,8 +44,7 @@ DisplayList::DisplayList()
, regions(stdAllocator)
, referenceHolders(stdAllocator)
, functors(stdAllocator)
- , vectorDrawables(stdAllocator) {
-}
+ , vectorDrawables(stdAllocator) {}
DisplayList::~DisplayList() {
cleanupResources();
@@ -105,14 +104,16 @@ void DisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) {
}
}
-bool DisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+bool DisplayList::prepareListAndChildren(
+ TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
info.prepareTextures = info.canvasContext.pinImages(bitmapResources);
for (auto&& op : children) {
RenderNode* childNode = op->renderNode;
info.damageAccumulator->pushTransform(&op->localMatrix);
- bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
+ bool childFunctorsNeedLayer =
+ functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
childFn(childNode, observer, info, childFunctorsNeedLayer);
info.damageAccumulator->popTransform();
}
@@ -140,5 +141,5 @@ void DisplayList::output(std::ostream& output, uint32_t level) {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index d22a764c0ea5..0cfc3b701aff 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -32,8 +32,8 @@
#include <androidfw/ResourceTypes.h>
-#include "Debug.h"
#include "CanvasProperty.h"
+#include "Debug.h"
#include "GlFunctorLifecycleListener.h"
#include "Matrix.h"
#include "RenderProperties.h"
@@ -74,6 +74,7 @@ struct FunctorContainer {
*/
class DisplayList {
friend class RecordingCanvas;
+
public:
struct Chunk {
// range of included ops in DisplayList::ops()
@@ -106,14 +107,9 @@ public:
size_t addChild(NodeOpType* childOp);
+ void ref(VirtualLightRefBase* prop) { referenceHolders.push_back(prop); }
- void ref(VirtualLightRefBase* prop) {
- referenceHolders.push_back(prop);
- }
-
- size_t getUsedSize() {
- return allocator.usedSize();
- }
+ size_t getUsedSize() { return allocator.usedSize(); }
virtual bool isEmpty() const { return ops.empty(); }
virtual bool hasFunctor() const { return !functors.empty(); }
@@ -125,7 +121,8 @@ public:
virtual void syncContents();
virtual void updateChildren(std::function<void(RenderNode*)> updateFn);
- virtual bool prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+ virtual bool prepareListAndChildren(
+ TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn);
virtual void output(std::ostream& output, uint32_t level);
@@ -148,12 +145,13 @@ private:
LsaVector<const Res_png_9patch*> patchResources;
LsaVector<std::unique_ptr<const SkPaint>> paints;
LsaVector<std::unique_ptr<const SkRegion>> regions;
- LsaVector< sp<VirtualLightRefBase> > referenceHolders;
+ LsaVector<sp<VirtualLightRefBase>> referenceHolders;
// List of functors
LsaVector<FunctorContainer> functors;
- // List of VectorDrawables that need to be notified of pushStaging. Note that this list gets nothing
+ // List of VectorDrawables that need to be notified of pushStaging. Note that this list gets
+ // nothing
// but a callback during sync DisplayList, unlike the list of functors defined above, which
// gets special treatment exclusive for webview.
LsaVector<VectorDrawableRoot*> vectorDrawables;
@@ -161,5 +159,5 @@ private:
void cleanupResources();
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index 69d5130e780f..530e82e65a28 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -31,7 +31,10 @@ namespace android {
namespace uirenderer {
Extensions::Extensions() {
- const char* version = (const char*) glGetString(GL_VERSION);
+ if (Properties::isSkiaEnabled()) {
+ return;
+ }
+ const char* version = (const char*)glGetString(GL_VERSION);
// Section 6.1.5 of the OpenGL ES specification indicates the GL version
// string strictly follows this format:
@@ -51,7 +54,7 @@ Extensions::Extensions() {
mVersionMinor = 0;
}
- auto extensions = StringUtils::split((const char*) glGetString(GL_EXTENSIONS));
+ auto extensions = StringUtils::split((const char*)glGetString(GL_EXTENSIONS));
mHasNPot = extensions.has("GL_OES_texture_npot");
mHasFramebufferFetch = extensions.has("GL_NV_shader_framebuffer_fetch");
mHasDiscardFramebuffer = extensions.has("GL_EXT_discard_framebuffer");
@@ -76,5 +79,5 @@ Extensions::Extensions() {
#endif
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 7af7f7944ac9..214ee0bbeefd 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -63,9 +63,9 @@ private:
int mVersionMajor;
int mVersionMinor;
-}; // class Extensions
+}; // class Extensions
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_EXTENSIONS_H
+#endif // ANDROID_HWUI_EXTENSIONS_H
diff --git a/libs/hwui/FboCache.cpp b/libs/hwui/FboCache.cpp
index a39e49f82eb0..88302cc52c2b 100644
--- a/libs/hwui/FboCache.cpp
+++ b/libs/hwui/FboCache.cpp
@@ -27,8 +27,7 @@ namespace uirenderer {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-FboCache::FboCache()
- : mMaxSize(0) {}
+FboCache::FboCache() : mMaxSize(0) {}
FboCache::~FboCache() {
clear();
@@ -79,5 +78,5 @@ bool FboCache::put(GLuint fbo) {
return false;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/FboCache.h b/libs/hwui/FboCache.h
index ad6cc3ea96c9..5e8bb0c7a7a7 100644
--- a/libs/hwui/FboCache.h
+++ b/libs/hwui/FboCache.h
@@ -71,9 +71,9 @@ public:
private:
SortedVector<GLuint> mCache;
uint32_t mMaxSize;
-}; // class FboCache
+}; // class FboCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_FBO_CACHE_H
+#endif // ANDROID_HWUI_FBO_CACHE_H
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
index a738ba4fe97e..b424f97a5004 100644
--- a/libs/hwui/FloatColor.h
+++ b/libs/hwui/FloatColor.h
@@ -33,8 +33,8 @@ struct FloatColor {
void set(uint32_t color) {
a = ((color >> 24) & 0xff) / 255.0f;
r = a * EOCF(((color >> 16) & 0xff) / 255.0f);
- g = a * EOCF(((color >> 8) & 0xff) / 255.0f);
- b = a * EOCF(((color ) & 0xff) / 255.0f);
+ g = a * EOCF(((color >> 8) & 0xff) / 255.0f);
+ b = a * EOCF(((color)&0xff) / 255.0f);
}
// "color" is a gamma-encoded sRGB color
@@ -44,27 +44,18 @@ struct FloatColor {
void setUnPreMultiplied(uint32_t color) {
a = ((color >> 24) & 0xff) / 255.0f;
r = EOCF(((color >> 16) & 0xff) / 255.0f);
- g = EOCF(((color >> 8) & 0xff) / 255.0f);
- b = EOCF(((color ) & 0xff) / 255.0f);
+ g = EOCF(((color >> 8) & 0xff) / 255.0f);
+ b = EOCF(((color)&0xff) / 255.0f);
}
- bool isNotBlack() {
- return a < 1.0f
- || r > 0.0f
- || g > 0.0f
- || b > 0.0f;
- }
+ bool isNotBlack() { return a < 1.0f || r > 0.0f || g > 0.0f || b > 0.0f; }
bool operator==(const FloatColor& other) const {
- return MathUtils::areEqual(r, other.r)
- && MathUtils::areEqual(g, other.g)
- && MathUtils::areEqual(b, other.b)
- && MathUtils::areEqual(a, other.a);
+ return MathUtils::areEqual(r, other.r) && MathUtils::areEqual(g, other.g) &&
+ MathUtils::areEqual(b, other.b) && MathUtils::areEqual(a, other.a);
}
- bool operator!=(const FloatColor& other) const {
- return !(*this == other);
- }
+ bool operator!=(const FloatColor& other) const { return !(*this == other); }
float r;
float g;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 8b0346867cbc..bbcedb15335d 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -22,20 +22,20 @@
#include "Caches.h"
#include "Debug.h"
#include "Extensions.h"
-#include "font/Font.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "PixelBuffer.h"
#include "Rect.h"
+#include "font/Font.h"
#include "renderstate/RenderState.h"
#include "utils/Blur.h"
#include "utils/Timing.h"
-#include <algorithm>
#include <RenderScript.h>
#include <SkGlyph.h>
#include <SkUtils.h>
#include <utils/Log.h>
+#include <algorithm>
namespace android {
namespace uirenderer {
@@ -55,8 +55,8 @@ void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
if (linearFiltering) {
textureFillFlags |= TextureFillFlags::ForceFilter;
}
- int transformFlags = pureTranslate
- ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
+ int transformFlags =
+ pureTranslate ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
bool gammaCorrection = true;
#else
@@ -93,7 +93,6 @@ FontRenderer::FontRenderer(const uint8_t* gammaTable)
, mDrawn(false)
, mInitialized(false)
, mLinearFiltering(false) {
-
if (sLogFontRendererCreate) {
INIT_LOGD("Creating FontRenderer");
}
@@ -118,10 +117,8 @@ FontRenderer::FontRenderer(const uint8_t* gammaTable)
if (sLogFontRendererCreate) {
INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i",
- mSmallCacheWidth, mSmallCacheHeight,
- mLargeCacheWidth, mLargeCacheHeight >> 1,
- mLargeCacheWidth, mLargeCacheHeight >> 1,
- mLargeCacheWidth, mLargeCacheHeight);
+ mSmallCacheWidth, mSmallCacheHeight, mLargeCacheWidth, mLargeCacheHeight >> 1,
+ mLargeCacheWidth, mLargeCacheHeight >> 1, mLargeCacheWidth, mLargeCacheHeight);
}
sLogFontRendererCreate = false;
@@ -195,7 +192,8 @@ void FontRenderer::flushLargeCaches() {
}
CacheTexture* FontRenderer::cacheBitmapInTexture(std::vector<CacheTexture*>& cacheTextures,
- const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) {
+ const SkGlyph& glyph, uint32_t* startX,
+ uint32_t* startY) {
for (uint32_t i = 0; i < cacheTextures.size(); i++) {
if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) {
return cacheTextures[i];
@@ -206,7 +204,7 @@ CacheTexture* FontRenderer::cacheBitmapInTexture(std::vector<CacheTexture*>& cac
}
void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
- uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) {
+ uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) {
checkInit();
// If the glyph bitmap is empty let's assum the glyph is valid
@@ -234,14 +232,14 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
#if DEBUG_FONT_RENDERER
ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format);
#endif
- return;
+ return;
}
// If the glyph is too tall, don't cache it
if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 >
- (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) {
- ALOGE("Font size too large to fit in cache. width, height = %i, %i",
- (int) glyph.fWidth, (int) glyph.fHeight);
+ (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) {
+ ALOGE("Font size too large to fit in cache. width, height = %i, %i", (int)glyph.fWidth,
+ (int)glyph.fHeight);
return;
}
@@ -285,14 +283,14 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
}
uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map();
- uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage;
+ uint8_t* bitmapBuffer = (uint8_t*)glyph.fImage;
int srcStride = glyph.rowBytes();
// Copy the glyph image, taking the mask format into account
switch (format) {
case SkMask::kA8_Format: {
- uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX
- - TEXTURE_BORDER_SIZE;
+ uint32_t row =
+ (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX - TEXTURE_BORDER_SIZE;
// write leading border line
memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
// write glyph data
@@ -337,9 +335,9 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
memset(dstL, 0, rowSize + 2 * borderSize);
// write glyph data
while (dst < dstEnd) {
- memset(dstL += dstStride, 0, borderSize); // leading border column
- memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data
- memset(dstR += dstStride, 0, borderSize); // trailing border column
+ memset(dstL += dstStride, 0, borderSize); // leading border column
+ memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data
+ memset(dstR += dstStride, 0, borderSize); // trailing border column
}
// write trailing border line
memset(dstL += dstStride, 0, rowSize + 2 * borderSize);
@@ -347,9 +345,9 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
}
case SkMask::kBW_Format: {
uint32_t cacheX = 0, cacheY = 0;
- uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX
- - TEXTURE_BORDER_SIZE;
- static const uint8_t COLORS[2] = { 0, 255 };
+ uint32_t row =
+ (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX - TEXTURE_BORDER_SIZE;
+ static const uint8_t COLORS[2] = {0, 255};
// write leading border line
memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
// write glyph data
@@ -388,7 +386,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
}
CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format,
- bool allocate) {
+ bool allocate) {
CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads);
if (allocate) {
@@ -405,18 +403,18 @@ void FontRenderer::initTextTexture() {
clearCacheTextures(mRGBACacheTextures);
mUploadTexture = false;
- mACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight,
- GL_ALPHA, true));
- mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
- GL_ALPHA, false));
- mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
- GL_ALPHA, false));
- mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight,
- GL_ALPHA, false));
- mRGBACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight,
- GL_RGBA, false));
- mRGBACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
- GL_RGBA, false));
+ mACacheTextures.push_back(
+ createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, GL_ALPHA, true));
+ mACacheTextures.push_back(
+ createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_ALPHA, false));
+ mACacheTextures.push_back(
+ createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_ALPHA, false));
+ mACacheTextures.push_back(
+ createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, GL_ALPHA, false));
+ mRGBACacheTextures.push_back(
+ createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, GL_RGBA, false));
+ mRGBACacheTextures.push_back(
+ createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_RGBA, false));
mCurrentCacheTexture = mACacheTextures[0];
}
@@ -432,7 +430,7 @@ void FontRenderer::checkInit() {
}
void checkTextureUpdateForCache(Caches& caches, std::vector<CacheTexture*>& cacheTextures,
- bool& resetPixelStore, GLuint& lastTextureId) {
+ bool& resetPixelStore, GLuint& lastTextureId) {
for (uint32_t i = 0; i < cacheTextures.size(); i++) {
CacheTexture* cacheTexture = cacheTextures[i];
if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) {
@@ -500,24 +498,22 @@ void FontRenderer::issueDrawCommand() {
issueDrawCommand(mRGBACacheTextures);
}
-void FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
- float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
- float x4, float y4, float u4, float v4, CacheTexture* texture) {
+void FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1, float x2, float y2,
+ float u2, float v2, float x3, float y3, float u3, float v3,
+ float x4, float y4, float u4, float v4,
+ CacheTexture* texture) {
if (texture != mCurrentCacheTexture) {
// Now use the new texture id
mCurrentCacheTexture = texture;
}
- mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2,
- x3, y3, u3, v3, x4, y4, u4, v4);
+ mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4);
}
-void FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1,
- float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
- float x4, float y4, float u4, float v4, CacheTexture* texture) {
-
- if (mClip &&
- (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) {
+void FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2,
+ float u2, float v2, float x3, float y3, float u3, float v3,
+ float x4, float y4, float u4, float v4, CacheTexture* texture) {
+ if (mClip && (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) {
return;
}
@@ -535,10 +531,10 @@ void FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1,
}
}
-void FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
- float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
- float x4, float y4, float u4, float v4, CacheTexture* texture) {
-
+void FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2,
+ float u2, float v2, float x3, float y3, float u3, float v3,
+ float x4, float y4, float u4, float v4,
+ CacheTexture* texture) {
appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture);
if (mBounds) {
@@ -557,8 +553,9 @@ void FontRenderer::setFont(const SkPaint* paint, const SkMatrix& matrix) {
mCurrentFont = Font::create(this, paint, matrix);
}
-FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const glyph_t *glyphs,
- int numGlyphs, float radius, const float* positions) {
+FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const glyph_t* glyphs,
+ int numGlyphs, float radius,
+ const float* positions) {
checkInit();
DropShadow image;
@@ -580,8 +577,8 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co
mCurrentFont->measure(paint, glyphs, numGlyphs, &bounds, positions);
uint32_t intRadius = Blur::convertRadiusToInt(radius);
- uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * intRadius;
- uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * intRadius;
+ uint32_t paddedWidth = (uint32_t)(bounds.right - bounds.left) + 2 * intRadius;
+ uint32_t paddedHeight = (uint32_t)(bounds.top - bounds.bottom) + 2 * intRadius;
uint32_t maxSize = Caches::getInstance().maxTextureSize;
if (paddedWidth > maxSize || paddedHeight > maxSize) {
@@ -593,7 +590,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co
paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT;
}
int size = paddedWidth * paddedHeight;
- uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size);
+ uint8_t* dataBuffer = (uint8_t*)memalign(RS_CPU_ALLOCATION_ALIGNMENT, size);
memset(dataBuffer, 0, size);
@@ -604,8 +601,8 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co
// text has non-whitespace, so draw and blur to create the shadow
// NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted
// TODO: don't draw pure whitespace in the first place, and avoid needing this check
- mCurrentFont->render(paint, glyphs, numGlyphs, penX, penY,
- Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, nullptr, positions);
+ mCurrentFont->render(paint, glyphs, numGlyphs, penX, penY, Font::BITMAP, dataBuffer,
+ paddedWidth, paddedHeight, nullptr, positions);
// Unbind any PBO we might have used
Caches::getInstance().pixelBufferState().unbind();
@@ -639,7 +636,7 @@ void FontRenderer::finishRender() {
}
void FontRenderer::precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
- const SkMatrix& matrix) {
+ const SkMatrix& matrix) {
Font* font = Font::create(this, paint, matrix);
font->precache(paint, glyphs, numGlyphs);
}
@@ -649,8 +646,8 @@ void FontRenderer::endPrecaching() {
}
bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs,
- int numGlyphs, int x, int y, const float* positions,
- Rect* bounds, TextDrawFunctor* functor, bool forceFinish) {
+ int numGlyphs, int x, int y, const float* positions, Rect* bounds,
+ TextDrawFunctor* functor, bool forceFinish) {
if (!mCurrentFont) {
ALOGE("No font set");
return false;
@@ -667,8 +664,8 @@ bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const g
}
bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs,
- int numGlyphs, const SkPath* path, float hOffset, float vOffset,
- Rect* bounds, TextDrawFunctor* functor) {
+ int numGlyphs, const SkPath* path, float hOffset, float vOffset,
+ Rect* bounds, TextDrawFunctor* functor) {
if (!mCurrentFont) {
ALOGE("No font set");
return false;
@@ -684,7 +681,7 @@ bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, cons
void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) {
uint32_t intRadius = Blur::convertRadiusToInt(radius);
if (width * height * intRadius >= RS_MIN_INPUT_CUTOFF && radius <= 25.0f) {
- uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);
+ uint8_t* outImage = (uint8_t*)memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);
if (mRs == nullptr) {
mRs = new RSC::RS();
@@ -700,14 +697,12 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, flo
}
if (mRs != nullptr) {
RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
- RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t,
- RS_ALLOCATION_MIPMAP_NONE,
- RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
- *image);
- RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t,
- RS_ALLOCATION_MIPMAP_NONE,
- RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
- outImage);
+ RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(
+ mRs, t, RS_ALLOCATION_MIPMAP_NONE,
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, *image);
+ RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(
+ mRs, t, RS_ALLOCATION_MIPMAP_NONE,
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, outImage);
mRsScript->setRadius(radius);
mRsScript->setInput(ain);
@@ -768,7 +763,7 @@ const std::vector<CacheTexture*>& FontRenderer::cacheTexturesForFormat(GLenum fo
}
static void dumpTextures(String8& log, const char* tag,
- const std::vector<CacheTexture*>& cacheTextures) {
+ const std::vector<CacheTexture*>& cacheTextures) {
for (uint32_t i = 0; i < cacheTextures.size(); i++) {
CacheTexture* cacheTexture = cacheTextures[i];
if (cacheTexture && cacheTexture->getPixelBuffer()) {
@@ -803,5 +798,5 @@ uint32_t FontRenderer::getSize() const {
return getCacheSize(GL_ALPHA) + getCacheSize(GL_RGBA);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 329309c1cd5c..6b9dec4719cb 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -16,10 +16,10 @@
#pragma once
-#include "font/FontUtil.h"
#include "font/CacheTexture.h"
#include "font/CachedGlyphInfo.h"
#include "font/Font.h"
+#include "font/FontUtil.h"
#ifdef BUGREPORT_FONT_CACHE_USAGE
#include "font/FontCacheHistoryTracker.h"
#endif
@@ -36,10 +36,10 @@
#include "RenderScript.h"
namespace RSC {
- class Element;
- class RS;
- class ScriptIntrinsicBlur;
- class sp;
+class Element;
+class RS;
+class ScriptIntrinsicBlur;
+class sp;
}
namespace android {
@@ -51,22 +51,18 @@ struct ClipBase;
class TextDrawFunctor {
public:
- TextDrawFunctor(
- BakedOpRenderer* renderer,
- const BakedOpState* bakedState,
- const ClipBase* clip,
- float x, float y, bool pureTranslate,
- int alpha, SkBlendMode mode, const SkPaint* paint)
- : renderer(renderer)
- , bakedState(bakedState)
- , clip(clip)
- , x(x)
- , y(y)
- , pureTranslate(pureTranslate)
- , alpha(alpha)
- , mode(mode)
- , paint(paint) {
- }
+ TextDrawFunctor(BakedOpRenderer* renderer, const BakedOpState* bakedState, const ClipBase* clip,
+ float x, float y, bool pureTranslate, int alpha, SkBlendMode mode,
+ const SkPaint* paint)
+ : renderer(renderer)
+ , bakedState(bakedState)
+ , clip(clip)
+ , x(x)
+ , y(y)
+ , pureTranslate(pureTranslate)
+ , alpha(alpha)
+ , mode(mode)
+ , paint(paint) {}
void draw(CacheTexture& texture, bool linearFiltering);
@@ -91,16 +87,17 @@ public:
void setFont(const SkPaint* paint, const SkMatrix& matrix);
- void precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, const SkMatrix& matrix);
+ void precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
+ const SkMatrix& matrix);
void endPrecaching();
- bool renderPosText(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs,
- int numGlyphs, int x, int y, const float* positions,
- Rect* outBounds, TextDrawFunctor* functor, bool forceFinish = true);
+ bool renderPosText(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs, int numGlyphs,
+ int x, int y, const float* positions, Rect* outBounds,
+ TextDrawFunctor* functor, bool forceFinish = true);
bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs,
- int numGlyphs, const SkPath* path,
- float hOffset, float vOffset, Rect* outBounds, TextDrawFunctor* functor);
+ int numGlyphs, const SkPath* path, float hOffset, float vOffset,
+ Rect* outBounds, TextDrawFunctor* functor);
struct DropShadow {
uint32_t width;
@@ -112,12 +109,10 @@ public:
// After renderDropShadow returns, the called owns the memory in DropShadow.image
// and is responsible for releasing it when it's done with it
- DropShadow renderDropShadow(const SkPaint* paint, const glyph_t *glyphs, int numGlyphs,
- float radius, const float* positions);
+ DropShadow renderDropShadow(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
+ float radius, const float* positions);
- void setTextureFiltering(bool linearFiltering) {
- mLinearFiltering = linearFiltering;
- }
+ void setTextureFiltering(bool linearFiltering) { mLinearFiltering = linearFiltering; }
uint32_t getSize() const;
void dumpMemoryUsage(String8& log) const;
@@ -135,10 +130,10 @@ private:
void deallocateTextureMemory(CacheTexture* cacheTexture);
void initTextTexture();
CacheTexture* createCacheTexture(int width, int height, GLenum format, bool allocate);
- void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
- uint32_t *retOriginX, uint32_t *retOriginY, bool precaching);
- CacheTexture* cacheBitmapInTexture(std::vector<CacheTexture*>& cacheTextures, const SkGlyph& glyph,
- uint32_t* startX, uint32_t* startY);
+ void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, uint32_t* retOriginX,
+ uint32_t* retOriginY, bool precaching);
+ CacheTexture* cacheBitmapInTexture(std::vector<CacheTexture*>& cacheTextures,
+ const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
void flushAllAndInvalidate();
@@ -148,24 +143,19 @@ private:
void issueDrawCommand(std::vector<CacheTexture*>& cacheTextures);
void issueDrawCommand();
- void appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
- float x2, float y2, float u2, float v2,
- float x3, float y3, float u3, float v3,
- float x4, float y4, float u4, float v4, CacheTexture* texture);
- void appendMeshQuad(float x1, float y1, float u1, float v1,
- float x2, float y2, float u2, float v2,
- float x3, float y3, float u3, float v3,
- float x4, float y4, float u4, float v4, CacheTexture* texture);
- void appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
- float x2, float y2, float u2, float v2,
- float x3, float y3, float u3, float v3,
- float x4, float y4, float u4, float v4, CacheTexture* texture);
+ void appendMeshQuadNoClip(float x1, float y1, float u1, float v1, float x2, float y2, float u2,
+ float v2, float x3, float y3, float u3, float v3, float x4, float y4,
+ float u4, float v4, CacheTexture* texture);
+ void appendMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2, float u2,
+ float v2, float x3, float y3, float u3, float v3, float x4, float y4,
+ float u4, float v4, CacheTexture* texture);
+ void appendRotatedMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2, float u2,
+ float v2, float x3, float y3, float u3, float v3, float x4, float y4,
+ float u4, float v4, CacheTexture* texture);
void checkTextureUpdate();
- void setTextureDirty() {
- mUploadTexture = true;
- }
+ void setTextureDirty() { mUploadTexture = true; }
const std::vector<CacheTexture*>& cacheTexturesForFormat(GLenum format) const;
uint32_t getCacheSize(GLenum format) const;
@@ -205,14 +195,14 @@ private:
RSC::sp<RSC::ScriptIntrinsicBlur> mRsScript;
static void computeGaussianWeights(float* weights, int32_t radius);
- static void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
- int32_t width, int32_t height);
- static void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
- int32_t width, int32_t height);
+ static void horizontalBlur(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest,
+ int32_t width, int32_t height);
+ static void verticalBlur(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest,
+ int32_t width, int32_t height);
// the input image handle may have its pointer replaced (to avoid copies)
void blurImage(uint8_t** image, int32_t width, int32_t height, float radius);
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 86f9a5d73fd1..ced37ede0746 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -20,8 +20,8 @@
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
#include "VectorDrawable.h"
-#include "renderstate/OffscreenBufferPool.h"
#include "hwui/Canvas.h"
+#include "renderstate/OffscreenBufferPool.h"
#include "utils/FatVector.h"
#include "utils/PaintUtils.h"
#include "utils/TraceUtils.h"
@@ -32,9 +32,8 @@
namespace android {
namespace uirenderer {
-FrameBuilder::FrameBuilder(const SkRect& clip,
- uint32_t viewportWidth, uint32_t viewportHeight,
- const LightGeometry& lightGeometry, Caches& caches)
+FrameBuilder::FrameBuilder(const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight,
+ const LightGeometry& lightGeometry, Caches& caches)
: mStdAllocator(mAllocator)
, mLayerBuilders(mStdAllocator)
, mLayerStack(mStdAllocator)
@@ -42,18 +41,16 @@ FrameBuilder::FrameBuilder(const SkRect& clip,
, mCaches(caches)
, mLightRadius(lightGeometry.radius)
, mDrawFbo0(true) {
-
// Prepare to defer Fbo0
auto fbo0 = mAllocator.create<LayerBuilder>(viewportWidth, viewportHeight, Rect(clip));
mLayerBuilders.push_back(fbo0);
mLayerStack.push_back(0);
- mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
- clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
- lightGeometry.center);
+ mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, clip.fLeft, clip.fTop,
+ clip.fRight, clip.fBottom, lightGeometry.center);
}
-FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers,
- const LightGeometry& lightGeometry, Caches& caches)
+FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const LightGeometry& lightGeometry,
+ Caches& caches)
: mStdAllocator(mAllocator)
, mLayerBuilders(mStdAllocator)
, mLayerStack(mStdAllocator)
@@ -67,9 +64,7 @@ FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers,
auto fbo0 = mAllocator.create<LayerBuilder>(1, 1, Rect(1, 1));
mLayerBuilders.push_back(fbo0);
mLayerStack.push_back(0);
- mCanvasState.initializeSaveStack(1, 1,
- 0, 0, 1, 1,
- lightGeometry.center);
+ mCanvasState.initializeSaveStack(1, 1, 0, 0, 1, 1, lightGeometry.center);
deferLayers(layers);
}
@@ -84,8 +79,8 @@ void FrameBuilder::deferLayers(const LayerUpdateQueue& layers) {
// as not to lose info on what portion is damaged
OffscreenBuffer* layer = layerNode->getLayer();
if (CC_LIKELY(layer)) {
- ATRACE_FORMAT("Optimize HW Layer DisplayList %s %ux%u",
- layerNode->getName(), layerNode->getWidth(), layerNode->getHeight());
+ ATRACE_FORMAT("Optimize HW Layer DisplayList %s %ux%u", layerNode->getName(),
+ layerNode->getWidth(), layerNode->getHeight());
Rect layerDamage = layers.entries()[i].damage;
// TODO: ensure layer damage can't be larger than layer
@@ -96,8 +91,8 @@ void FrameBuilder::deferLayers(const LayerUpdateQueue& layers) {
Vector3 lightCenter = mCanvasState.currentSnapshot()->getRelativeLightCenter();
layer->inverseTransformInWindow.mapPoint3d(lightCenter);
- saveForLayer(layerNode->getWidth(), layerNode->getHeight(), 0, 0,
- layerDamage, lightCenter, nullptr, layerNode);
+ saveForLayer(layerNode->getWidth(), layerNode->getHeight(), 0, 0, layerDamage,
+ lightCenter, nullptr, layerNode);
if (layerNode->getDisplayList()) {
deferNodeOps(*layerNode);
@@ -121,19 +116,18 @@ void FrameBuilder::deferRenderNode(float tx, float ty, Rect clipRect, RenderNode
mCanvasState.save(SaveFlags::MatrixClip);
mCanvasState.translate(tx, ty);
mCanvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
- SkClipOp::kIntersect);
+ SkClipOp::kIntersect);
deferNodePropsAndOps(renderNode);
mCanvasState.restore();
}
static Rect nodeBounds(RenderNode& node) {
auto& props = node.properties();
- return Rect(props.getLeft(), props.getTop(),
- props.getRight(), props.getBottom());
+ return Rect(props.getLeft(), props.getTop(), props.getRight(), props.getBottom());
}
-void FrameBuilder::deferRenderNodeScene(const std::vector< sp<RenderNode> >& nodes,
- const Rect& contentDrawBounds) {
+void FrameBuilder::deferRenderNodeScene(const std::vector<sp<RenderNode> >& nodes,
+ const Rect& contentDrawBounds) {
if (nodes.size() < 1) return;
if (nodes.size() == 1) {
if (!nodes[0]->nothingToDraw()) {
@@ -170,14 +164,16 @@ void FrameBuilder::deferRenderNodeScene(const std::vector< sp<RenderNode> >& nod
// the backdrop, so this isn't necessary.
if (content.right < backdrop.right) {
// draw backdrop to right side of content
- deferRenderNode(0, 0, Rect(content.right, backdrop.top,
- backdrop.right, backdrop.bottom), *nodes[0]);
+ deferRenderNode(0, 0,
+ Rect(content.right, backdrop.top, backdrop.right, backdrop.bottom),
+ *nodes[0]);
}
if (content.bottom < backdrop.bottom) {
// draw backdrop to bottom of content
// Note: bottom fill uses content left/right, to avoid overdrawing left/right fill
- deferRenderNode(0, 0, Rect(content.left, content.bottom,
- content.right, backdrop.bottom), *nodes[0]);
+ deferRenderNode(0, 0,
+ Rect(content.left, content.bottom, content.right, backdrop.bottom),
+ *nodes[0]);
}
}
@@ -210,11 +206,9 @@ void FrameBuilder::onSnapshotRestored(const Snapshot& removed, const Snapshot& r
void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
const RenderProperties& properties = node.properties();
const Outline& outline = properties.getOutline();
- if (properties.getAlpha() <= 0
- || (outline.getShouldClip() && outline.isEmpty())
- || properties.getScaleX() == 0
- || properties.getScaleY() == 0) {
- return; // rejected
+ if (properties.getAlpha() <= 0 || (outline.getShouldClip() && outline.isEmpty()) ||
+ properties.getScaleX() == 0 || properties.getScaleY() == 0) {
+ return; // rejected
}
if (properties.getLeft() != 0 || properties.getTop() != 0) {
@@ -236,12 +230,12 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
const int width = properties.getWidth();
const int height = properties.getHeight();
- Rect saveLayerBounds; // will be set to non-empty if saveLayer needed
+ Rect saveLayerBounds; // will be set to non-empty if saveLayer needed
const bool isLayer = properties.effectiveLayerType() != LayerType::None;
int clipFlags = properties.getClippingFlags();
if (properties.getAlpha() < 1) {
if (isLayer) {
- clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
+ clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
}
if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) {
// simply scale rendering content's alpha
@@ -251,7 +245,7 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
saveLayerBounds.set(0, 0, width, height);
if (clipFlags) {
properties.getClippingRectForFlags(clipFlags, &saveLayerBounds);
- clipFlags = 0; // all clipping done by savelayer
+ clipFlags = 0; // all clipping done by savelayer
}
}
@@ -265,21 +259,21 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
Rect clipRect;
properties.getClippingRectForFlags(clipFlags, &clipRect);
mCanvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
- SkClipOp::kIntersect);
+ SkClipOp::kIntersect);
}
if (properties.getRevealClip().willClip()) {
Rect bounds;
properties.getRevealClip().getBounds(&bounds);
- mCanvasState.setClippingRoundRect(mAllocator,
- bounds, properties.getRevealClip().getRadius());
+ mCanvasState.setClippingRoundRect(mAllocator, bounds,
+ properties.getRevealClip().getRadius());
} else if (properties.getOutline().willClip()) {
mCanvasState.setClippingOutline(mAllocator, &(properties.getOutline()));
}
- bool quickRejected = mCanvasState.currentSnapshot()->getRenderTargetClip().isEmpty()
- || (properties.getClipToBounds()
- && mCanvasState.quickRejectConservative(0, 0, width, height));
+ bool quickRejected = mCanvasState.currentSnapshot()->getRenderTargetClip().isEmpty() ||
+ (properties.getClipToBounds() &&
+ mCanvasState.quickRejectConservative(0, 0, width, height));
if (!quickRejected) {
// not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer)
if (node.getLayer()) {
@@ -296,9 +290,8 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
SkPaint saveLayerPaint;
saveLayerPaint.setAlpha(properties.getAlpha());
deferBeginLayerOp(*mAllocator.create_trivial<BeginLayerOp>(
- saveLayerBounds,
- Matrix4::identity(),
- nullptr, // no record-time clip - need only respect defer-time one
+ saveLayerBounds, Matrix4::identity(),
+ nullptr, // no record-time clip - need only respect defer-time one
&saveLayerPaint));
deferNodeOps(node);
deferEndLayerOp(*mAllocator.create_trivial<EndLayerOp>());
@@ -311,8 +304,8 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
typedef key_value_pair_t<float, const RenderNodeOp*> ZRenderNodeOpPair;
template <typename V>
-static void buildZSortedChildList(V* zTranslatedNodes,
- const DisplayList& displayList, const DisplayList::Chunk& chunk) {
+static void buildZSortedChildList(V* zTranslatedNodes, const DisplayList& displayList,
+ const DisplayList::Chunk& chunk) {
if (chunk.beginChildIndex == chunk.endChildIndex) return;
for (size_t i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
@@ -343,11 +336,10 @@ static size_t findNonNegativeIndex(const V& zTranslatedNodes) {
template <typename V>
void FrameBuilder::defer3dChildren(const ClipBase* reorderClip, ChildrenSelectMode mode,
- const V& zTranslatedNodes) {
+ const V& zTranslatedNodes) {
const int size = zTranslatedNodes.size();
- if (size == 0
- || (mode == ChildrenSelectMode::Negative&& zTranslatedNodes[0].key > 0.0f)
- || (mode == ChildrenSelectMode::Positive && zTranslatedNodes[size - 1].key < 0.0f)) {
+ if (size == 0 || (mode == ChildrenSelectMode::Negative && zTranslatedNodes[0].key > 0.0f) ||
+ (mode == ChildrenSelectMode::Positive && zTranslatedNodes[size - 1].key < 0.0f)) {
// no 3d children to draw
return;
}
@@ -364,11 +356,11 @@ void FrameBuilder::defer3dChildren(const ClipBase* reorderClip, ChildrenSelectMo
if (mode == ChildrenSelectMode::Negative) {
drawIndex = 0;
endIndex = nonNegativeIndex;
- shadowIndex = endIndex; // draw no shadows
+ shadowIndex = endIndex; // draw no shadows
} else {
drawIndex = nonNegativeIndex;
endIndex = size;
- shadowIndex = drawIndex; // potentially draw shadow for each pos Z child
+ shadowIndex = drawIndex; // potentially draw shadow for each pos Z child
}
float lastCasterZ = 0.0f;
@@ -381,7 +373,7 @@ void FrameBuilder::defer3dChildren(const ClipBase* reorderClip, ChildrenSelectMo
if (shadowIndex == drawIndex || casterZ - lastCasterZ < 0.1f) {
deferShadow(reorderClip, *casterNodeOp);
- lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
+ lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
shadowIndex++;
continue;
}
@@ -397,11 +389,9 @@ void FrameBuilder::deferShadow(const ClipBase* reorderClip, const RenderNodeOp&
auto& node = *casterNodeOp.renderNode;
auto& properties = node.properties();
- if (properties.getAlpha() <= 0.0f
- || properties.getOutline().getAlpha() <= 0.0f
- || !properties.getOutline().getPath()
- || properties.getScaleX() == 0
- || properties.getScaleY() == 0) {
+ if (properties.getAlpha() <= 0.0f || properties.getOutline().getAlpha() <= 0.0f ||
+ !properties.getOutline().getPath() || properties.getScaleX() == 0 ||
+ properties.getScaleY() == 0) {
// no shadow to draw
return;
}
@@ -432,8 +422,8 @@ void FrameBuilder::deferShadow(const ClipBase* reorderClip, const RenderNodeOp&
Rect clipBounds;
properties.getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds);
SkPath clipBoundsPath;
- clipBoundsPath.addRect(clipBounds.left, clipBounds.top,
- clipBounds.right, clipBounds.bottom);
+ clipBoundsPath.addRect(clipBounds.left, clipBounds.top, clipBounds.right,
+ clipBounds.bottom);
Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, frameAllocatedPath);
casterPath = frameAllocatedPath;
@@ -442,7 +432,7 @@ void FrameBuilder::deferShadow(const ClipBase* reorderClip, const RenderNodeOp&
// apply reorder clip to shadow, so it respects clip at beginning of reorderable chunk
int restoreTo = mCanvasState.save(SaveFlags::MatrixClip);
mCanvasState.writableSnapshot()->applyClip(reorderClip,
- *mCanvasState.currentSnapshot()->transform);
+ *mCanvasState.currentSnapshot()->transform);
if (CC_LIKELY(!mCanvasState.getRenderTargetClipBounds().isEmpty())) {
Matrix4 shadowMatrixXY(casterNodeOp.localMatrix);
Matrix4 shadowMatrixZ(casterNodeOp.localMatrix);
@@ -450,13 +440,9 @@ void FrameBuilder::deferShadow(const ClipBase* reorderClip, const RenderNodeOp&
node.applyViewPropertyTransforms(shadowMatrixZ, true);
sp<TessellationCache::ShadowTask> task = mCaches.tessellationCache.getShadowTask(
- mCanvasState.currentTransform(),
- mCanvasState.getLocalClipBounds(),
- casterAlpha >= 1.0f,
- casterPath,
- &shadowMatrixXY, &shadowMatrixZ,
- mCanvasState.currentSnapshot()->getRelativeLightCenter(),
- mLightRadius);
+ mCanvasState.currentTransform(), mCanvasState.getLocalClipBounds(),
+ casterAlpha >= 1.0f, casterPath, &shadowMatrixXY, &shadowMatrixZ,
+ mCanvasState.currentSnapshot()->getRelativeLightCenter(), mLightRadius);
ShadowOp* shadowOp = mAllocator.create<ShadowOp>(task, casterAlpha);
BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct(
mAllocator, *mCanvasState.writableSnapshot(), shadowOp);
@@ -471,15 +457,13 @@ void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
int count = mCanvasState.save(SaveFlags::MatrixClip);
const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
- SkPath transformedMaskPath; // on stack, since BakedOpState makes a deep copy
+ SkPath transformedMaskPath; // on stack, since BakedOpState makes a deep copy
if (projectionReceiverOutline) {
// transform the mask for this projector into render target space
// TODO: consider combining both transforms by stashing transform instead of applying
SkMatrix skCurrentTransform;
mCanvasState.currentTransform()->copyTo(skCurrentTransform);
- projectionReceiverOutline->transform(
- skCurrentTransform,
- &transformedMaskPath);
+ projectionReceiverOutline->transform(skCurrentTransform, &transformedMaskPath);
mCanvasState.setProjectionPathMask(&transformedMaskPath);
}
@@ -509,10 +493,12 @@ void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
* This allows opIds embedded in the RecordedOps to be used for dispatching to these lambdas.
* E.g. a BitmapOp op then would be dispatched to FrameBuilder::onBitmapOp(const BitmapOp&)
*/
-#define OP_RECEIVER(Type) \
- [](FrameBuilder& frameBuilder, const RecordedOp& op) { frameBuilder.defer##Type(static_cast<const Type&>(op)); },
+#define OP_RECEIVER(Type) \
+ [](FrameBuilder& frameBuilder, const RecordedOp& op) { \
+ frameBuilder.defer##Type(static_cast<const Type&>(op)); \
+ },
void FrameBuilder::deferNodeOps(const RenderNode& renderNode) {
- typedef void (*OpDispatcher) (FrameBuilder& frameBuilder, const RecordedOp& op);
+ typedef void (*OpDispatcher)(FrameBuilder & frameBuilder, const RecordedOp& op);
static OpDispatcher receivers[] = BUILD_DEFERRABLE_OP_LUT(OP_RECEIVER);
// can't be null, since DL=null node rejection happens before deferNodePropsAndOps
@@ -526,9 +512,9 @@ void FrameBuilder::deferNodeOps(const RenderNode& renderNode) {
const RecordedOp* op = displayList.getOps()[opIndex];
receivers[op->opId](*this, *op);
- if (CC_UNLIKELY(!renderNode.mProjectedNodes.empty()
- && displayList.projectionReceiveIndex >= 0
- && static_cast<int>(opIndex) == displayList.projectionReceiveIndex)) {
+ if (CC_UNLIKELY(!renderNode.mProjectedNodes.empty() &&
+ displayList.projectionReceiveIndex >= 0 &&
+ static_cast<int>(opIndex) == displayList.projectionReceiveIndex)) {
deferProjectedChildren(renderNode);
}
}
@@ -542,7 +528,7 @@ void FrameBuilder::deferRenderNodeOpImpl(const RenderNodeOp& op) {
// apply state from RecordedOp (clip first, since op's clip is transformed by current matrix)
mCanvasState.writableSnapshot()->applyClip(op.localClip,
- *mCanvasState.currentSnapshot()->transform);
+ *mCanvasState.currentSnapshot()->transform);
mCanvasState.concatMatrix(op.localMatrix);
// then apply state from node properties, and defer ops
@@ -562,12 +548,12 @@ void FrameBuilder::deferRenderNodeOp(const RenderNodeOp& op) {
* for paint's style on the bounds being computed.
*/
BakedOpState* FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
- BakedOpState::StrokeBehavior strokeBehavior, bool expandForPathTexture) {
+ BakedOpState::StrokeBehavior strokeBehavior,
+ bool expandForPathTexture) {
// Note: here we account for stroke when baking the op
BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
- mAllocator, *mCanvasState.writableSnapshot(), op,
- strokeBehavior, expandForPathTexture);
- if (!bakedState) return nullptr; // quick rejected
+ mAllocator, *mCanvasState.writableSnapshot(), op, strokeBehavior, expandForPathTexture);
+ if (!bakedState) return nullptr; // quick rejected
if (op.opId == RecordedOpId::RectOp && op.paint->getStyle() != SkPaint::kStroke_Style) {
bakedState->setupOpacity(op.paint);
@@ -586,8 +572,8 @@ BakedOpState* FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t ba
static batchid_t tessBatchId(const RecordedOp& op) {
const SkPaint& paint = *(op.paint);
return paint.getPathEffect()
- ? OpBatchType::AlphaMaskTexture
- : (paint.isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices);
+ ? OpBatchType::AlphaMaskTexture
+ : (paint.isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices);
}
void FrameBuilder::deferArcOp(const ArcOp& op) {
@@ -598,13 +584,13 @@ void FrameBuilder::deferArcOp(const ArcOp& op) {
}
static bool hasMergeableClip(const BakedOpState& state) {
- return !state.computedState.clipState
- || state.computedState.clipState->mode == ClipMode::Rectangle;
+ return !state.computedState.clipState ||
+ state.computedState.clipState->mode == ClipMode::Rectangle;
}
void FrameBuilder::deferBitmapOp(const BitmapOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
if (op.bitmap->isOpaque()) {
bakedState->setupOpacity(op.paint);
@@ -613,11 +599,10 @@ void FrameBuilder::deferBitmapOp(const BitmapOp& op) {
// Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
// Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
// MergingDrawBatch::canMergeWith()
- if (bakedState->computedState.transform.isSimple()
- && bakedState->computedState.transform.positiveScale()
- && PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver
- && op.bitmap->colorType() != kAlpha_8_SkColorType
- && hasMergeableClip(*bakedState)) {
+ if (bakedState->computedState.transform.isSimple() &&
+ bakedState->computedState.transform.positiveScale() &&
+ PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver &&
+ op.bitmap->colorType() != kAlpha_8_SkColorType && hasMergeableClip(*bakedState)) {
mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.bitmap->getGenerationID());
currentLayer().deferMergeableOp(mAllocator, bakedState, OpBatchType::Bitmap, mergeId);
} else {
@@ -627,24 +612,21 @@ void FrameBuilder::deferBitmapOp(const BitmapOp& op) {
void FrameBuilder::deferBitmapMeshOp(const BitmapMeshOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
}
void FrameBuilder::deferBitmapRectOp(const BitmapRectOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
}
void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) {
Bitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty();
SkPaint* paint = op.vectorDrawable->getPaint();
- const BitmapRectOp* resolvedOp = mAllocator.create_trivial<BitmapRectOp>(op.unmappedBounds,
- op.localMatrix,
- op.localClip,
- paint,
- &bitmap,
+ const BitmapRectOp* resolvedOp = mAllocator.create_trivial<BitmapRectOp>(
+ op.unmappedBounds, op.localMatrix, op.localClip, paint, &bitmap,
Rect(bitmap.width(), bitmap.height()));
deferBitmapRectOp(*resolvedOp);
}
@@ -656,23 +638,20 @@ void FrameBuilder::deferCirclePropsOp(const CirclePropsOp& op) {
float y = *(op.y);
float radius = *(op.radius);
Rect unmappedBounds(x - radius, y - radius, x + radius, y + radius);
- const OvalOp* resolvedOp = mAllocator.create_trivial<OvalOp>(
- unmappedBounds,
- op.localMatrix,
- op.localClip,
- op.paint);
+ const OvalOp* resolvedOp = mAllocator.create_trivial<OvalOp>(unmappedBounds, op.localMatrix,
+ op.localClip, op.paint);
deferOvalOp(*resolvedOp);
}
void FrameBuilder::deferColorOp(const ColorOp& op) {
BakedOpState* bakedState = tryBakeUnboundedOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Vertices);
}
void FrameBuilder::deferFunctorOp(const FunctorOp& op) {
BakedOpState* bakedState = tryBakeUnboundedOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Functor);
}
@@ -687,11 +666,11 @@ void FrameBuilder::deferOvalOp(const OvalOp& op) {
void FrameBuilder::deferPatchOp(const PatchOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
- if (bakedState->computedState.transform.isPureTranslate()
- && PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver
- && hasMergeableClip(*bakedState)) {
+ if (bakedState->computedState.transform.isPureTranslate() &&
+ PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver &&
+ hasMergeableClip(*bakedState)) {
mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.bitmap->getGenerationID());
// Only use the MergedPatch batchId when merged, so Bitmap+Patch don't try to merge together
@@ -723,7 +702,8 @@ void FrameBuilder::deferRoundRectOp(const RoundRectOp& op) {
if (CC_LIKELY(state && !op.paint->getPathEffect())) {
// TODO: consider storing tessellation task in BakedOpState
mCaches.tessellationCache.precacheRoundRect(state->computedState.transform, *(op.paint),
- op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.rx, op.ry);
+ op.unmappedBounds.getWidth(),
+ op.unmappedBounds.getHeight(), op.rx, op.ry);
}
}
@@ -731,16 +711,14 @@ void FrameBuilder::deferRoundRectPropsOp(const RoundRectPropsOp& op) {
// allocate a temporary round rect op (with mAllocator, so it persists until render), so the
// renderer doesn't have to handle the RoundRectPropsOp type, and so state baking is simple.
const RoundRectOp* resolvedOp = mAllocator.create_trivial<RoundRectOp>(
- Rect(*(op.left), *(op.top), *(op.right), *(op.bottom)),
- op.localMatrix,
- op.localClip,
+ Rect(*(op.left), *(op.top), *(op.right), *(op.bottom)), op.localMatrix, op.localClip,
op.paint, *op.rx, *op.ry);
deferRoundRectOp(*resolvedOp);
}
void FrameBuilder::deferSimpleRectsOp(const SimpleRectsOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Vertices);
}
@@ -753,12 +731,12 @@ void FrameBuilder::deferTextOp(const TextOp& op) {
BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
mAllocator, *mCanvasState.writableSnapshot(), op,
BakedOpState::StrokeBehavior::StyleDefined, false);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
batchid_t batchId = textBatchId(*(op.paint));
- if (bakedState->computedState.transform.isPureTranslate()
- && PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver
- && hasMergeableClip(*bakedState)) {
+ if (bakedState->computedState.transform.isPureTranslate() &&
+ PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver &&
+ hasMergeableClip(*bakedState)) {
mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.paint->getColor());
currentLayer().deferMergeableOp(mAllocator, bakedState, batchId, mergeId);
} else {
@@ -773,19 +751,19 @@ void FrameBuilder::deferTextOp(const TextOp& op) {
// Partial transform case, see BakedOpDispatcher::renderTextOp
float sx, sy;
totalTransform.decomposeScale(sx, sy);
- fontRenderer.precache(op.paint, op.glyphs, op.glyphCount, SkMatrix::MakeScale(
- roundf(std::max(1.0f, sx)),
- roundf(std::max(1.0f, sy))));
+ fontRenderer.precache(
+ op.paint, op.glyphs, op.glyphCount,
+ SkMatrix::MakeScale(roundf(std::max(1.0f, sx)), roundf(std::max(1.0f, sy))));
}
}
void FrameBuilder::deferTextOnPathOp(const TextOnPathOp& op) {
BakedOpState* bakedState = tryBakeUnboundedOpState(op);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint)));
- mCaches.fontRenderer.getFontRenderer().precache(
- op.paint, op.glyphs, op.glyphCount, SkMatrix::I());
+ mCaches.fontRenderer.getFontRenderer().precache(op.paint, op.glyphs, op.glyphCount,
+ SkMatrix::I());
}
void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) {
@@ -802,28 +780,27 @@ void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) {
}
BakedOpState* bakedState = tryBakeOpState(*textureLayerOp);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::TextureLayer);
}
-void FrameBuilder::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
- float contentTranslateX, float contentTranslateY,
- const Rect& repaintRect,
- const Vector3& lightCenter,
- const BeginLayerOp* beginLayerOp, RenderNode* renderNode) {
+void FrameBuilder::saveForLayer(uint32_t layerWidth, uint32_t layerHeight, float contentTranslateX,
+ float contentTranslateY, const Rect& repaintRect,
+ const Vector3& lightCenter, const BeginLayerOp* beginLayerOp,
+ RenderNode* renderNode) {
mCanvasState.save(SaveFlags::MatrixClip);
mCanvasState.writableSnapshot()->initializeViewport(layerWidth, layerHeight);
mCanvasState.writableSnapshot()->roundRectClipState = nullptr;
mCanvasState.writableSnapshot()->setRelativeLightCenter(lightCenter);
- mCanvasState.writableSnapshot()->transform->loadTranslate(
- contentTranslateX, contentTranslateY, 0);
- mCanvasState.writableSnapshot()->setClip(
- repaintRect.left, repaintRect.top, repaintRect.right, repaintRect.bottom);
+ mCanvasState.writableSnapshot()->transform->loadTranslate(contentTranslateX, contentTranslateY,
+ 0);
+ mCanvasState.writableSnapshot()->setClip(repaintRect.left, repaintRect.top, repaintRect.right,
+ repaintRect.bottom);
// create a new layer repaint, and push its index on the stack
mLayerStack.push_back(mLayerBuilders.size());
- auto newFbo = mAllocator.create<LayerBuilder>(layerWidth, layerHeight,
- repaintRect, beginLayerOp, renderNode);
+ auto newFbo = mAllocator.create<LayerBuilder>(layerWidth, layerHeight, repaintRect,
+ beginLayerOp, renderNode);
mLayerBuilders.push_back(newFbo);
}
@@ -836,8 +813,8 @@ void FrameBuilder::restoreForLayer() {
// TODO: defer time rejection (when bounds become empty) + tests
// Option - just skip layers with no bounds at playback + defer?
void FrameBuilder::deferBeginLayerOp(const BeginLayerOp& op) {
- uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth();
- uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight();
+ uint32_t layerWidth = (uint32_t)op.unmappedBounds.getWidth();
+ uint32_t layerHeight = (uint32_t)op.unmappedBounds.getHeight();
auto previous = mCanvasState.currentSnapshot();
Vector3 lightCenter = previous->getRelativeLightCenter();
@@ -873,11 +850,8 @@ void FrameBuilder::deferBeginLayerOp(const BeginLayerOp& op) {
float contentTranslateX = -saveLayerBounds.left;
float contentTranslateY = -saveLayerBounds.top;
- saveForLayer(layerWidth, layerHeight,
- contentTranslateX, contentTranslateY,
- Rect(layerWidth, layerHeight),
- lightCenter,
- &op, nullptr);
+ saveForLayer(layerWidth, layerHeight, contentTranslateX, contentTranslateY,
+ Rect(layerWidth, layerHeight), lightCenter, &op, nullptr);
}
void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {
@@ -890,8 +864,8 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {
// to translate the drawLayer by how much the contents was translated
// TODO: Unify this with beginLayerOp so we don't have to calculate this
// twice
- uint32_t layerWidth = (uint32_t) beginLayerOp.unmappedBounds.getWidth();
- uint32_t layerHeight = (uint32_t) beginLayerOp.unmappedBounds.getHeight();
+ uint32_t layerWidth = (uint32_t)beginLayerOp.unmappedBounds.getWidth();
+ uint32_t layerHeight = (uint32_t)beginLayerOp.unmappedBounds.getHeight();
auto previous = mCanvasState.currentSnapshot();
Vector3 lightCenter = previous->getRelativeLightCenter();
@@ -900,8 +874,7 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {
// parent content transform * canvas transform * bounds offset
Matrix4 contentTransform(*(previous->transform));
contentTransform.multiply(beginLayerOp.localMatrix);
- contentTransform.translate(beginLayerOp.unmappedBounds.left,
- beginLayerOp.unmappedBounds.top);
+ contentTransform.translate(beginLayerOp.unmappedBounds.left, beginLayerOp.unmappedBounds.top);
Matrix4 inverseContentTransform;
inverseContentTransform.loadInverse(contentTransform);
@@ -927,10 +900,7 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {
// record the draw operation into the previous layer's list of draw commands
// uses state from the associated beginLayerOp, since it has all the state needed for drawing
LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(
- beginLayerOp.unmappedBounds,
- localMatrix,
- beginLayerOp.localClip,
- beginLayerOp.paint,
+ beginLayerOp.unmappedBounds, localMatrix, beginLayerOp.localClip, beginLayerOp.paint,
&(mLayerBuilders[finishedLayerIndex]->offscreenBuffer));
BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp);
@@ -959,15 +929,16 @@ void FrameBuilder::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) {
// Unclipped layer rejected - push a null op, so next EndUnclippedLayerOp is ignored
currentLayer().activeUnclippedSaveLayers.push_back(nullptr);
} else {
- // Allocate a holding position for the layer object (copyTo will produce, copyFrom will consume)
+ // Allocate a holding position for the layer object (copyTo will produce, copyFrom will
+ // consume)
OffscreenBuffer** layerHandle = mAllocator.create<OffscreenBuffer*>(nullptr);
/**
* First, defer an operation to copy out the content from the rendertarget into a layer.
*/
auto copyToOp = mAllocator.create_trivial<CopyToLayerOp>(op, layerHandle);
- BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator,
- &(currentLayer().repaintClip), dstRect, *copyToOp);
+ BakedOpState* bakedState = BakedOpState::directConstruct(
+ mAllocator, &(currentLayer().repaintClip), dstRect, *copyToOp);
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer);
/**
@@ -981,8 +952,8 @@ void FrameBuilder::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) {
* a balanced EndUnclippedLayerOp is seen
*/
auto copyFromOp = mAllocator.create_trivial<CopyFromLayerOp>(op, layerHandle);
- bakedState = BakedOpState::directConstruct(mAllocator,
- &(currentLayer().repaintClip), dstRect, *copyFromOp);
+ bakedState = BakedOpState::directConstruct(mAllocator, &(currentLayer().repaintClip),
+ dstRect, *copyFromOp);
currentLayer().activeUnclippedSaveLayers.push_back(bakedState);
}
}
@@ -1001,5 +972,5 @@ void FrameBuilder::finishDefer() {
mCaches.fontRenderer.endPrecaching();
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index 46048f7125ce..974daf8a17bb 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -23,8 +23,8 @@
#include "RecordedOp.h"
#include "utils/GLUtils.h"
-#include <vector>
#include <unordered_map>
+#include <vector>
struct SkRect;
@@ -60,12 +60,11 @@ public:
float radius;
};
- FrameBuilder(const SkRect& clip,
- uint32_t viewportWidth, uint32_t viewportHeight,
- const LightGeometry& lightGeometry, Caches& caches);
+ FrameBuilder(const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight,
+ const LightGeometry& lightGeometry, Caches& caches);
- FrameBuilder(const LayerUpdateQueue& layerUpdateQueue,
- const LightGeometry& lightGeometry, Caches& caches);
+ FrameBuilder(const LayerUpdateQueue& layerUpdateQueue, const LightGeometry& lightGeometry,
+ Caches& caches);
void deferLayers(const LayerUpdateQueue& layers);
@@ -73,8 +72,8 @@ public:
void deferRenderNode(float tx, float ty, Rect clipRect, RenderNode& renderNode);
- void deferRenderNodeScene(const std::vector< sp<RenderNode> >& nodes,
- const Rect& contentDrawBounds);
+ void deferRenderNodeScene(const std::vector<sp<RenderNode> >& nodes,
+ const Rect& contentDrawBounds);
virtual ~FrameBuilder() {}
@@ -88,32 +87,32 @@ public:
void replayBakedOps(Renderer& renderer) {
std::vector<OffscreenBuffer*> temporaryLayers;
finishDefer();
- /**
- * Defines a LUT of lambdas which allow a recorded BakedOpState to use state->op->opId to
- * dispatch the op via a method on a static dispatcher when the op is replayed.
- *
- * For example a BitmapOp would resolve, via the lambda lookup, to calling:
- *
- * StaticDispatcher::onBitmapOp(Renderer& renderer, const BitmapOp& op, const BakedOpState& state);
- */
- #define X(Type) \
- [](void* renderer, const BakedOpState& state) { \
- StaticDispatcher::on##Type(*(static_cast<Renderer*>(renderer)), \
- static_cast<const Type&>(*(state.op)), state); \
- },
+/**
+ * Defines a LUT of lambdas which allow a recorded BakedOpState to use state->op->opId to
+ * dispatch the op via a method on a static dispatcher when the op is replayed.
+ *
+ * For example a BitmapOp would resolve, via the lambda lookup, to calling:
+ *
+ * StaticDispatcher::onBitmapOp(Renderer& renderer, const BitmapOp& op, const BakedOpState& state);
+ */
+#define X(Type) \
+ [](void* renderer, const BakedOpState& state) { \
+ StaticDispatcher::on##Type(*(static_cast<Renderer*>(renderer)), \
+ static_cast<const Type&>(*(state.op)), state); \
+ },
static BakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X);
- #undef X
-
- /**
- * Defines a LUT of lambdas which allow merged arrays of BakedOpState* to be passed to a
- * static dispatcher when the group of merged ops is replayed.
- */
- #define X(Type) \
- [](void* renderer, const MergedBakedOpList& opList) { \
- StaticDispatcher::onMerged##Type##s(*(static_cast<Renderer*>(renderer)), opList); \
- },
+#undef X
+
+/**
+ * Defines a LUT of lambdas which allow merged arrays of BakedOpState* to be passed to a
+ * static dispatcher when the group of merged ops is replayed.
+ */
+#define X(Type) \
+ [](void* renderer, const MergedBakedOpList& opList) { \
+ StaticDispatcher::onMerged##Type##s(*(static_cast<Renderer*>(renderer)), opList); \
+ },
static MergedOpReceiver mergedReceivers[] = BUILD_MERGEABLE_OP_LUT(X);
- #undef X
+#undef X
// Relay through layers in reverse order, since layers
// later in the list will be drawn by earlier ones
@@ -168,15 +167,10 @@ public:
private:
void finishDefer();
- enum class ChildrenSelectMode {
- Negative,
- Positive
- };
- void saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
- float contentTranslateX, float contentTranslateY,
- const Rect& repaintRect,
- const Vector3& lightCenter,
- const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
+ enum class ChildrenSelectMode { Negative, Positive };
+ void saveForLayer(uint32_t layerWidth, uint32_t layerHeight, float contentTranslateX,
+ float contentTranslateY, const Rect& repaintRect, const Vector3& lightCenter,
+ const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
void restoreForLayer();
LayerBuilder& currentLayer() { return *(mLayerBuilders[mLayerStack.back()]); }
@@ -185,16 +179,16 @@ private:
return BakedOpState::tryConstruct(mAllocator, *mCanvasState.writableSnapshot(), recordedOp);
}
BakedOpState* tryBakeUnboundedOpState(const RecordedOp& recordedOp) {
- return BakedOpState::tryConstructUnbounded(mAllocator, *mCanvasState.writableSnapshot(), recordedOp);
+ return BakedOpState::tryConstructUnbounded(mAllocator, *mCanvasState.writableSnapshot(),
+ recordedOp);
}
-
// should always be surrounded by a save/restore pair, and not called if DisplayList is null
void deferNodePropsAndOps(RenderNode& node);
template <typename V>
void defer3dChildren(const ClipBase* reorderClip, ChildrenSelectMode mode,
- const V& zTranslatedNodes);
+ const V& zTranslatedNodes);
void deferShadow(const ClipBase* reorderClip, const RenderNodeOp& casterOp);
@@ -206,20 +200,19 @@ private:
void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers);
- SkPath* createFrameAllocatedPath() {
- return mAllocator.create<SkPath>();
- }
+ SkPath* createFrameAllocatedPath() { return mAllocator.create<SkPath>(); }
BakedOpState* deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
- BakedOpState::StrokeBehavior strokeBehavior = BakedOpState::StrokeBehavior::StyleDefined,
- bool expandForPathTexture = false);
+ BakedOpState::StrokeBehavior strokeBehavior =
+ BakedOpState::StrokeBehavior::StyleDefined,
+ bool expandForPathTexture = false);
- /**
- * Declares all FrameBuilder::deferXXXXOp() methods for every RecordedOp type.
- *
- * These private methods are called from within deferImpl to defer each individual op
- * type differently.
- */
+/**
+ * Declares all FrameBuilder::deferXXXXOp() methods for every RecordedOp type.
+ *
+ * These private methods are called from within deferImpl to defer each individual op
+ * type differently.
+ */
#define X(Type) void defer##Type(const Type& op);
MAP_DEFERRABLE_OPS(X)
#undef X
@@ -254,5 +247,5 @@ private:
const bool mDrawFbo0;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 826f0bba294c..71cc9a81a09f 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -21,30 +21,30 @@ namespace android {
namespace uirenderer {
const std::string FrameInfoNames[] = {
- "Flags",
- "IntendedVsync",
- "Vsync",
- "OldestInputEvent",
- "NewestInputEvent",
- "HandleInputStart",
- "AnimationStart",
- "PerformTraversalsStart",
- "DrawStart",
- "SyncQueued",
- "SyncStart",
- "IssueDrawCommandsStart",
- "SwapBuffers",
- "FrameCompleted",
- "DequeueBufferDuration",
- "QueueBufferDuration",
+ "Flags",
+ "IntendedVsync",
+ "Vsync",
+ "OldestInputEvent",
+ "NewestInputEvent",
+ "HandleInputStart",
+ "AnimationStart",
+ "PerformTraversalsStart",
+ "DrawStart",
+ "SyncQueued",
+ "SyncStart",
+ "IssueDrawCommandsStart",
+ "SwapBuffers",
+ "FrameCompleted",
+ "DequeueBufferDuration",
+ "QueueBufferDuration",
};
-static_assert((sizeof(FrameInfoNames)/sizeof(FrameInfoNames[0]))
- == static_cast<int>(FrameInfoIndex::NumIndexes),
- "size mismatch: FrameInfoNames doesn't match the enum!");
+static_assert((sizeof(FrameInfoNames) / sizeof(FrameInfoNames[0])) ==
+ static_cast<int>(FrameInfoIndex::NumIndexes),
+ "size mismatch: FrameInfoNames doesn't match the enum!");
static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 16,
- "Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");
+ "Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");
void FrameInfo::importUiThreadInfo(int64_t* info) {
memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index bac9d12d273c..0aab58c38ba0 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -59,12 +59,12 @@ enum class FrameInfoIndex {
extern const std::string FrameInfoNames[];
namespace FrameInfoFlags {
- enum {
- WindowLayoutChanged = 1 << 0,
- RTAnimation = 1 << 1,
- SurfaceCanvas = 1 << 2,
- SkippedFrame = 1 << 3,
- };
+enum {
+ WindowLayoutChanged = 1 << 0,
+ RTAnimation = 1 << 1,
+ SurfaceCanvas = 1 << 2,
+ SkippedFrame = 1 << 3,
+};
};
class ANDROID_API UiFrameInfoBuilder {
@@ -91,9 +91,7 @@ public:
}
private:
- inline int64_t& set(FrameInfoIndex index) {
- return mBuffer[static_cast<int>(index)];
- }
+ inline int64_t& set(FrameInfoIndex index) { return mBuffer[static_cast<int>(index)]; }
int64_t* mBuffer;
};
@@ -102,33 +100,23 @@ class FrameInfo {
public:
void importUiThreadInfo(int64_t* info);
- void markSyncStart() {
- set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC);
- }
+ void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC); }
void markIssueDrawCommandsStart() {
set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
}
- void markSwapBuffers() {
- set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC);
- }
+ void markSwapBuffers() { set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC); }
- void markFrameCompleted() {
- set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC);
- }
+ void markFrameCompleted() { set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC); }
void addFlag(int frameInfoFlag) {
set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
}
- const int64_t* data() const {
- return mFrameInfo;
- }
+ const int64_t* data() const { return mFrameInfo; }
- inline int64_t operator[](FrameInfoIndex index) const {
- return get(index);
- }
+ inline int64_t operator[](FrameInfoIndex index) const { return get(index); }
inline int64_t operator[](int index) const {
if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
@@ -140,12 +128,10 @@ public:
int64_t starttime = get(start);
int64_t gap = endtime - starttime;
gap = starttime > 0 ? gap : 0;
- if (end > FrameInfoIndex::SyncQueued &&
- start < FrameInfoIndex::SyncQueued) {
+ if (end > FrameInfoIndex::SyncQueued && start < FrameInfoIndex::SyncQueued) {
// Need to subtract out the time spent in a stalled state
// as this will be captured by the previous frame's info
- int64_t offset = get(FrameInfoIndex::SyncStart)
- - get(FrameInfoIndex::SyncQueued);
+ int64_t offset = get(FrameInfoIndex::SyncStart) - get(FrameInfoIndex::SyncQueued);
if (offset > 0) {
gap -= offset;
}
@@ -157,9 +143,7 @@ public:
return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
}
- inline int64_t& set(FrameInfoIndex index) {
- return mFrameInfo[static_cast<int>(index)];
- }
+ inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; }
inline int64_t get(FrameInfoIndex index) const {
if (index == FrameInfoIndex::NumIndexes) return 0;
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index d3adc32da848..5aea04d94cbe 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -22,8 +22,10 @@
#include <cutils/compiler.h>
#include <array>
-#define RETURN_IF_PROFILING_DISABLED() if (CC_LIKELY(mType == ProfileType::None)) return
-#define RETURN_IF_DISABLED() if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return
+#define RETURN_IF_PROFILING_DISABLED() \
+ if (CC_LIKELY(mType == ProfileType::None)) return
+#define RETURN_IF_DISABLED() \
+ if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return
#define PROFILE_DRAW_WIDTH 3
#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
@@ -48,22 +50,22 @@ struct BarSegment {
SkColor color;
};
-static const std::array<BarSegment,7> Bar {{
- { FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, Color::Teal_700 },
- { FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart, Color::Green_700 },
- { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, Color::LightGreen_700 },
- { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, Color::Blue_500 },
- { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, Color::LightBlue_300 },
- { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, Color::Red_500},
- { FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, Color::Orange_500},
+static const std::array<BarSegment, 7> Bar{{
+ {FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, Color::Teal_700},
+ {FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart,
+ Color::Green_700},
+ {FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, Color::LightGreen_700},
+ {FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, Color::Blue_500},
+ {FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, Color::LightBlue_300},
+ {FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, Color::Red_500},
+ {FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, Color::Orange_500},
}};
static int dpToPx(int dp, float density) {
- return (int) (dp * density + 0.5f);
+ return (int)(dp * density + 0.5f);
}
-FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source)
- : mFrameSource(source) {
+FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
setDensity(1);
}
@@ -97,8 +99,8 @@ void FrameInfoVisualizer::draw(IProfileRenderer& renderer) {
if (mFlashToggle) {
SkPaint paint;
paint.setColor(0x7fff0000);
- renderer.drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop,
- mDirtyRegion.fRight, mDirtyRegion.fBottom, paint);
+ renderer.drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop, mDirtyRegion.fRight,
+ mDirtyRegion.fBottom, paint);
}
}
@@ -169,7 +171,8 @@ void FrameInfoVisualizer::initializeRects(const int baseline, const int width) {
void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex end) {
int fast_i = (mNumFastRects - 1) * 4;
- int janky_i = (mNumJankyRects - 1) * 4;;
+ int janky_i = (mNumJankyRects - 1) * 4;
+ ;
for (size_t fi = 0; fi < mFrameSource.size(); fi++) {
if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) {
continue;
@@ -210,11 +213,8 @@ void FrameInfoVisualizer::drawThreshold(IProfileRenderer& renderer) {
SkPaint paint;
paint.setColor(THRESHOLD_COLOR);
float yLocation = renderer.getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
- renderer.drawRect(0.0f,
- yLocation - mThresholdStroke/2,
- renderer.getViewportWidth(),
- yLocation + mThresholdStroke/2,
- paint);
+ renderer.drawRect(0.0f, yLocation - mThresholdStroke / 2, renderer.getViewportWidth(),
+ yLocation + mThresholdStroke / 2, paint);
}
bool FrameInfoVisualizer::consumeProperties() {
@@ -245,22 +245,19 @@ void FrameInfoVisualizer::dumpData(int fd) {
// last call to dumpData(). In other words if there's a dumpData(), draw frame,
// dumpData(), the last dumpData() should only log 1 frame.
- FILE *file = fdopen(fd, "a");
- fprintf(file, "\n\tDraw\tPrepare\tProcess\tExecute\n");
+ dprintf(fd, "\n\tDraw\tPrepare\tProcess\tExecute\n");
for (size_t i = 0; i < mFrameSource.size(); i++) {
if (mFrameSource[i][FrameInfoIndex::IntendedVsync] <= mLastFrameLogged) {
continue;
}
mLastFrameLogged = mFrameSource[i][FrameInfoIndex::IntendedVsync];
- fprintf(file, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n",
+ dprintf(fd, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n",
durationMS(i, FrameInfoIndex::IntendedVsync, FrameInfoIndex::SyncStart),
durationMS(i, FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart),
durationMS(i, FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers),
durationMS(i, FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted));
}
-
- fflush(file);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/FrameMetricsObserver.h b/libs/hwui/FrameMetricsObserver.h
index 4f81c8681fc8..ba72e937095f 100644
--- a/libs/hwui/FrameMetricsObserver.h
+++ b/libs/hwui/FrameMetricsObserver.h
@@ -26,5 +26,5 @@ public:
virtual void notify(const int64_t* buffer);
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/FrameMetricsReporter.h b/libs/hwui/FrameMetricsReporter.h
index c1cd0a9224b6..d920a99f5ee3 100644
--- a/libs/hwui/FrameMetricsReporter.h
+++ b/libs/hwui/FrameMetricsReporter.h
@@ -16,8 +16,8 @@
#pragma once
-#include <utils/RefBase.h>
#include <utils/Log.h>
+#include <utils/RefBase.h>
#include "FrameInfo.h"
#include "FrameMetricsObserver.h"
@@ -32,9 +32,7 @@ class FrameMetricsReporter {
public:
FrameMetricsReporter() {}
- void addObserver(FrameMetricsObserver* observer) {
- mObservers.push_back(observer);
- }
+ void addObserver(FrameMetricsObserver* observer) { mObservers.push_back(observer); }
bool removeObserver(FrameMetricsObserver* observer) {
for (size_t i = 0; i < mObservers.size(); i++) {
@@ -46,9 +44,7 @@ public:
return false;
}
- bool hasObservers() {
- return mObservers.size() > 0;
- }
+ bool hasObservers() { return mObservers.size() > 0; }
void reportFrameMetrics(const int64_t* stats) {
for (size_t i = 0; i < mObservers.size(); i++) {
@@ -57,9 +53,8 @@ public:
}
private:
- std::vector< sp<FrameMetricsObserver> > mObservers;
+ std::vector<sp<FrameMetricsObserver> > mObservers;
};
-}; // namespace uirenderer
-}; // namespace android
-
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index 8aff0a24b4f0..88fb16234388 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "Debug.h"
#include "GammaFontRenderer.h"
+#include "Debug.h"
#include "Properties.h"
namespace android {
@@ -39,5 +39,5 @@ void GammaFontRenderer::endPrecaching() {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index c9cf69bc7d9f..e9002442c64f 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -26,9 +26,7 @@ class GammaFontRenderer {
public:
GammaFontRenderer();
- void clear() {
- mRenderer.reset(nullptr);
- }
+ void clear() { mRenderer.reset(nullptr); }
void flush() {
if (mRenderer) {
@@ -55,9 +53,7 @@ public:
}
}
- uint32_t getSize() const {
- return mRenderer ? mRenderer->getSize() : 0;
- }
+ uint32_t getSize() const { return mRenderer ? mRenderer->getSize() : 0; }
void endPrecaching();
@@ -68,7 +64,7 @@ private:
#endif
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_GAMMA_FONT_RENDERER_H
+#endif // ANDROID_HWUI_GAMMA_FONT_RENDERER_H
diff --git a/libs/hwui/GlFunctorLifecycleListener.h b/libs/hwui/GlFunctorLifecycleListener.h
index 357090eb31ca..5d07b46919d4 100644
--- a/libs/hwui/GlFunctorLifecycleListener.h
+++ b/libs/hwui/GlFunctorLifecycleListener.h
@@ -28,5 +28,5 @@ public:
virtual void onGlFunctorReleased(Functor* functor) = 0;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp
index 070e95432a11..42ae29d76898 100644
--- a/libs/hwui/GlLayer.cpp
+++ b/libs/hwui/GlLayer.cpp
@@ -23,17 +23,16 @@
#include <utils/Log.h>
-#define ATRACE_LAYER_WORK(label) \
- ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \
- label, \
- (renderNode.get() != NULL) ? renderNode->getName() : "", \
- getWidth(), getHeight())
+#define ATRACE_LAYER_WORK(label) \
+ ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", label, \
+ (renderNode.get() != NULL) ? renderNode->getName() : "", getWidth(), \
+ getHeight())
namespace android {
namespace uirenderer {
GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
- SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend)
+ sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend)
: Layer(renderState, Api::OpenGL, colorFilter, alpha, mode)
, caches(Caches::getInstance())
, texture(caches) {
@@ -73,5 +72,5 @@ void GlLayer::generateTexture() {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h
index c4f7fe2a56b8..28749a0d125c 100644
--- a/libs/hwui/GlLayer.h
+++ b/libs/hwui/GlLayer.h
@@ -32,45 +32,29 @@ class Caches;
class GlLayer : public Layer {
public:
GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
- SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend);
+ sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend);
virtual ~GlLayer();
- uint32_t getWidth() const override {
- return texture.mWidth;
- }
+ uint32_t getWidth() const override { return texture.mWidth; }
- uint32_t getHeight() const override {
- return texture.mHeight;
- }
+ uint32_t getHeight() const override { return texture.mHeight; }
void setSize(uint32_t width, uint32_t height) override {
texture.updateLayout(width, height, texture.internalFormat(), texture.format(),
- texture.target());
+ texture.target());
}
- void setBlend(bool blend) override {
- texture.blend = blend;
- }
+ void setBlend(bool blend) override { texture.blend = blend; }
- bool isBlend() const override {
- return texture.blend;
- }
+ bool isBlend() const override { return texture.blend; }
- inline GLuint getTextureId() const {
- return texture.id();
- }
+ inline GLuint getTextureId() const { return texture.id(); }
- inline Texture& getTexture() {
- return texture;
- }
+ inline Texture& getTexture() { return texture; }
- inline GLenum getRenderTarget() const {
- return texture.target();
- }
+ inline GLenum getRenderTarget() const { return texture.target(); }
- inline bool isRenderable() const {
- return texture.target() != GL_NONE;
- }
+ inline bool isRenderable() const { return texture.target() != GL_NONE; }
void setRenderTarget(GLenum renderTarget);
@@ -89,7 +73,7 @@ private:
* The texture backing this layer.
*/
Texture texture;
-}; // struct GlLayer
+}; // struct GlLayer
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index e91c08d5a351..c68d51604bea 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -41,34 +41,34 @@ class Texture;
*/
namespace VertexAttribFlags {
- enum {
- // Mesh is pure x,y vertex pairs
- None = 0,
- // Mesh has texture coordinates embedded. Note that texture can exist without this flag
- // being set, if coordinates passed to sampler are determined another way.
- TextureCoord = 1 << 0,
- // Mesh has color embedded (to export to varying)
- Color = 1 << 1,
- // Mesh has alpha embedded (to export to varying)
- Alpha = 1 << 2,
- };
+enum {
+ // Mesh is pure x,y vertex pairs
+ None = 0,
+ // Mesh has texture coordinates embedded. Note that texture can exist without this flag
+ // being set, if coordinates passed to sampler are determined another way.
+ TextureCoord = 1 << 0,
+ // Mesh has color embedded (to export to varying)
+ Color = 1 << 1,
+ // Mesh has alpha embedded (to export to varying)
+ Alpha = 1 << 2,
+};
};
/*
* Enumerates transform features
*/
namespace TransformFlags {
- enum {
- None = 0,
+enum {
+ None = 0,
- // offset the eventual drawing matrix by a tiny amount to
- // disambiguate sampling patterns with non-AA rendering
- OffsetByFudgeFactor = 1 << 0,
+ // offset the eventual drawing matrix by a tiny amount to
+ // disambiguate sampling patterns with non-AA rendering
+ OffsetByFudgeFactor = 1 << 0,
- // Canvas transform isn't applied to the mesh at draw time,
- // since it's already built in.
- MeshIgnoresCanvasTransform = 1 << 1, // TODO: remove for HWUI_NEW_OPS
- };
+ // Canvas transform isn't applied to the mesh at draw time,
+ // since it's already built in.
+ MeshIgnoresCanvasTransform = 1 << 1, // TODO: remove for HWUI_NEW_OPS
+};
};
/**
@@ -86,10 +86,11 @@ namespace TransformFlags {
*/
struct Glop {
PREVENT_COPY_AND_ASSIGN(Glop);
+
public:
- Glop() { }
+ Glop() {}
struct Mesh {
- GLuint primitiveMode; // GL_TRIANGLES and GL_TRIANGLE_STRIP supported
+ GLuint primitiveMode; // GL_TRIANGLES and GL_TRIANGLE_STRIP supported
// buffer object and void* are mutually exclusive.
// Only GL_UNSIGNED_SHORT supported.
@@ -110,7 +111,7 @@ public:
} vertices;
int elementCount;
- int vertexCount; // only used for meshes (for glDrawRangeElements)
+ int vertexCount; // only used for meshes (for glDrawRangeElements)
TextureVertex mappedVertices[4];
} mesh;
@@ -148,10 +149,11 @@ public:
Matrix4 canvas;
int transformFlags;
- const Matrix4& meshTransform() const {
- return (transformFlags & TransformFlags::MeshIgnoresCanvasTransform)
- ? Matrix4::identity() : canvas;
- }
+ const Matrix4& meshTransform() const {
+ return (transformFlags & TransformFlags::MeshIgnoresCanvasTransform)
+ ? Matrix4::identity()
+ : canvas;
+ }
} transform;
const RoundRectClipState* roundRectClipState = nullptr;
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index c19c1a11e3e2..2f107a004731 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -22,12 +22,12 @@
#include "Matrix.h"
#include "Patch.h"
#include "PathCache.h"
-#include "renderstate/MeshState.h"
-#include "renderstate/RenderState.h"
#include "SkiaShader.h"
#include "Texture.h"
-#include "utils/PaintUtils.h"
#include "VertexBuffer.h"
+#include "renderstate/MeshState.h"
+#include "renderstate/RenderState.h"
+#include "utils/PaintUtils.h"
#include <GLES2/gl2.h>
#include <SkPaint.h>
@@ -36,13 +36,13 @@
#if DEBUG_GLOP_BUILDER
-#define TRIGGER_STAGE(stageFlag) \
- LOG_ALWAYS_FATAL_IF((stageFlag) & mStageFlags, "Stage %d cannot be run twice", (stageFlag)); \
+#define TRIGGER_STAGE(stageFlag) \
+ LOG_ALWAYS_FATAL_IF((stageFlag)&mStageFlags, "Stage %d cannot be run twice", (stageFlag)); \
mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag))
-#define REQUIRE_STAGES(requiredFlags) \
+#define REQUIRE_STAGES(requiredFlags) \
LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \
- "not prepared for current stage")
+ "not prepared for current stage")
#else
@@ -62,10 +62,7 @@ static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {
}
GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
- : mRenderState(renderState)
- , mCaches(caches)
- , mShader(nullptr)
- , mOutGlop(outGlop) {
+ : mRenderState(renderState), mCaches(caches), mShader(nullptr), mOutGlop(outGlop) {
mStageFlags = kInitialStage;
}
@@ -77,12 +74,10 @@ GlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementC
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
- mOutGlop->mesh.vertices = {
- vbo,
- VertexAttribFlags::TextureCoord,
- nullptr, (const void*) kMeshTextureOffset, nullptr,
- kTextureVertexStride };
+ mOutGlop->mesh.indices = {mRenderState.meshState().getQuadListIBO(), nullptr};
+ mOutGlop->mesh.vertices = {vbo, VertexAttribFlags::TextureCoord,
+ nullptr, (const void*)kMeshTextureOffset,
+ nullptr, kTextureVertexStride};
mOutGlop->mesh.elementCount = elementCount;
return *this;
}
@@ -91,12 +86,13 @@ GlopBuilder& GlopBuilder::setMeshUnitQuad() {
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
- mOutGlop->mesh.indices = { 0, nullptr };
- mOutGlop->mesh.vertices = {
- mRenderState.meshState().getUnitQuadVBO(),
- VertexAttribFlags::None,
- nullptr, nullptr, nullptr,
- kTextureVertexStride };
+ mOutGlop->mesh.indices = {0, nullptr};
+ mOutGlop->mesh.vertices = {mRenderState.meshState().getUnitQuadVBO(),
+ VertexAttribFlags::None,
+ nullptr,
+ nullptr,
+ nullptr,
+ kTextureVertexStride};
mOutGlop->mesh.elementCount = 4;
return *this;
}
@@ -110,12 +106,13 @@ GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) {
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
- mOutGlop->mesh.indices = { 0, nullptr };
- mOutGlop->mesh.vertices = {
- mRenderState.meshState().getUnitQuadVBO(),
- VertexAttribFlags::TextureCoord,
- nullptr, (const void*) kMeshTextureOffset, nullptr,
- kTextureVertexStride };
+ mOutGlop->mesh.indices = {0, nullptr};
+ mOutGlop->mesh.vertices = {mRenderState.meshState().getUnitQuadVBO(),
+ VertexAttribFlags::TextureCoord,
+ nullptr,
+ (const void*)kMeshTextureOffset,
+ nullptr,
+ kTextureVertexStride};
mOutGlop->mesh.elementCount = 4;
return *this;
}
@@ -130,12 +127,13 @@ GlopBuilder& GlopBuilder::setMeshTexturedUvQuad(const UvMapper* uvMapper, Rect u
const TextureVertex* textureVertex = mOutGlop->mesh.mappedVertices;
mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
- mOutGlop->mesh.indices = { 0, nullptr };
- mOutGlop->mesh.vertices = {
- 0,
- VertexAttribFlags::TextureCoord,
- &textureVertex[0].x, &textureVertex[0].u, nullptr,
- kTextureVertexStride };
+ mOutGlop->mesh.indices = {0, nullptr};
+ mOutGlop->mesh.vertices = {0,
+ VertexAttribFlags::TextureCoord,
+ &textureVertex[0].x,
+ &textureVertex[0].u,
+ nullptr,
+ kTextureVertexStride};
mOutGlop->mesh.elementCount = 4;
return *this;
}
@@ -144,12 +142,9 @@ GlopBuilder& GlopBuilder::setMeshIndexedQuads(Vertex* vertexData, int quadCount)
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
+ mOutGlop->mesh.indices = {mRenderState.meshState().getQuadListIBO(), nullptr};
mOutGlop->mesh.vertices = {
- 0,
- VertexAttribFlags::None,
- vertexData, nullptr, nullptr,
- kVertexStride };
+ 0, VertexAttribFlags::None, vertexData, nullptr, nullptr, kVertexStride};
mOutGlop->mesh.elementCount = 6 * quadCount;
return *this;
}
@@ -158,26 +153,29 @@ GlopBuilder& GlopBuilder::setMeshTexturedIndexedQuads(TextureVertex* vertexData,
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
- mOutGlop->mesh.vertices = {
- 0,
- VertexAttribFlags::TextureCoord,
- &vertexData[0].x, &vertexData[0].u, nullptr,
- kTextureVertexStride };
+ mOutGlop->mesh.indices = {mRenderState.meshState().getQuadListIBO(), nullptr};
+ mOutGlop->mesh.vertices = {0,
+ VertexAttribFlags::TextureCoord,
+ &vertexData[0].x,
+ &vertexData[0].u,
+ nullptr,
+ kTextureVertexStride};
mOutGlop->mesh.elementCount = elementCount;
return *this;
}
-GlopBuilder& GlopBuilder::setMeshColoredTexturedMesh(ColorTextureVertex* vertexData, int elementCount) {
+GlopBuilder& GlopBuilder::setMeshColoredTexturedMesh(ColorTextureVertex* vertexData,
+ int elementCount) {
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.indices = { 0, nullptr };
- mOutGlop->mesh.vertices = {
- 0,
- VertexAttribFlags::TextureCoord | VertexAttribFlags::Color,
- &vertexData[0].x, &vertexData[0].u, &vertexData[0].r,
- kColorTextureVertexStride };
+ mOutGlop->mesh.indices = {0, nullptr};
+ mOutGlop->mesh.vertices = {0,
+ VertexAttribFlags::TextureCoord | VertexAttribFlags::Color,
+ &vertexData[0].x,
+ &vertexData[0].u,
+ &vertexData[0].r,
+ kColorTextureVertexStride};
mOutGlop->mesh.elementCount = elementCount;
return *this;
}
@@ -191,15 +189,16 @@ GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer)
bool indices = flags & VertexBuffer::kIndices;
mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
- mOutGlop->mesh.indices = { 0, vertexBuffer.getIndices() };
- mOutGlop->mesh.vertices = {
- 0,
- alphaVertex ? VertexAttribFlags::Alpha : VertexAttribFlags::None,
- vertexBuffer.getBuffer(), nullptr, nullptr,
- alphaVertex ? kAlphaVertexStride : kVertexStride };
- mOutGlop->mesh.elementCount = indices
- ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount();
- mOutGlop->mesh.vertexCount = vertexBuffer.getVertexCount(); // used for glDrawRangeElements()
+ mOutGlop->mesh.indices = {0, vertexBuffer.getIndices()};
+ mOutGlop->mesh.vertices = {0,
+ alphaVertex ? VertexAttribFlags::Alpha : VertexAttribFlags::None,
+ vertexBuffer.getBuffer(),
+ nullptr,
+ nullptr,
+ alphaVertex ? kAlphaVertexStride : kVertexStride};
+ mOutGlop->mesh.elementCount =
+ indices ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount();
+ mOutGlop->mesh.vertexCount = vertexBuffer.getVertexCount(); // used for glDrawRangeElements()
return *this;
}
@@ -207,12 +206,13 @@ GlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) {
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
- mOutGlop->mesh.vertices = {
- mCaches.patchCache.getMeshBuffer(),
- VertexAttribFlags::TextureCoord,
- (void*)patch.positionOffset, (void*)patch.textureOffset, nullptr,
- kTextureVertexStride };
+ mOutGlop->mesh.indices = {mRenderState.meshState().getQuadListIBO(), nullptr};
+ mOutGlop->mesh.vertices = {mCaches.patchCache.getMeshBuffer(),
+ VertexAttribFlags::TextureCoord,
+ (void*)patch.positionOffset,
+ (void*)patch.textureOffset,
+ nullptr,
+ kTextureVertexStride};
mOutGlop->mesh.elementCount = patch.indexCount;
return *this;
}
@@ -221,9 +221,9 @@ GlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) {
// Fill
////////////////////////////////////////////////////////////////////////////////
-void GlopBuilder::setFill(int color, float alphaScale,
- SkBlendMode mode, Blend::ModeOrderSwap modeUsage,
- const SkShader* shader, const SkColorFilter* colorFilter) {
+void GlopBuilder::setFill(int color, float alphaScale, SkBlendMode mode,
+ Blend::ModeOrderSwap modeUsage, const SkShader* shader,
+ const SkColorFilter* colorFilter) {
if (mode != SkBlendMode::kClear) {
if (!shader) {
FloatColor c;
@@ -235,23 +235,20 @@ void GlopBuilder::setFill(int color, float alphaScale,
mOutGlop->fill.color = c;
} else {
float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
- mOutGlop->fill.color = { 1, 1, 1, alpha };
+ mOutGlop->fill.color = {1, 1, 1, alpha};
}
} else {
- mOutGlop->fill.color = { 0, 0, 0, 1 };
+ mOutGlop->fill.color = {0, 0, 0, 1};
}
- mOutGlop->blend = { GL_ZERO, GL_ZERO };
- if (mOutGlop->fill.color.a < 1.0f
- || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
- || (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend)
- || mOutGlop->roundRectClipState
- || PaintUtils::isBlendedShader(shader)
- || PaintUtils::isBlendedColorFilter(colorFilter)
- || mode != SkBlendMode::kSrcOver) {
+ mOutGlop->blend = {GL_ZERO, GL_ZERO};
+ if (mOutGlop->fill.color.a < 1.0f ||
+ (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha) ||
+ (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend) ||
+ mOutGlop->roundRectClipState || PaintUtils::isBlendedShader(shader) ||
+ PaintUtils::isBlendedColorFilter(colorFilter) || mode != SkBlendMode::kSrcOver) {
if (CC_LIKELY(mode <= SkBlendMode::kScreen)) {
- Blend::getFactors(mode, modeUsage,
- &mOutGlop->blend.src, &mOutGlop->blend.dst);
+ Blend::getFactors(mode, modeUsage, &mOutGlop->blend.src, &mOutGlop->blend.dst);
} else {
// These blend modes are not supported by OpenGL directly and have
// to be implemented using shaders. Since the shader will perform
@@ -264,23 +261,25 @@ void GlopBuilder::setFill(int color, float alphaScale,
// blending in shader, don't enable
} else {
// unsupported
- Blend::getFactors(SkBlendMode::kSrcOver, modeUsage,
- &mOutGlop->blend.src, &mOutGlop->blend.dst);
+ Blend::getFactors(SkBlendMode::kSrcOver, modeUsage, &mOutGlop->blend.src,
+ &mOutGlop->blend.dst);
}
}
}
- mShader = shader; // shader resolved in ::build()
+ mShader = shader; // shader resolved in ::build()
if (colorFilter) {
SkColor color;
SkBlendMode bmode;
SkScalar srcColorMatrix[20];
if (colorFilter->asColorMode(&color, &bmode)) {
- mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
+ mOutGlop->fill.filterMode = mDescription.colorOp =
+ ProgramDescription::ColorFilterMode::Blend;
mDescription.colorMode = bmode;
mOutGlop->fill.filter.color.set(color);
} else if (colorFilter->asColorMatrix(srcColorMatrix)) {
- mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;
+ mOutGlop->fill.filterMode = mDescription.colorOp =
+ ProgramDescription::ColorFilterMode::Matrix;
float* colorMatrix = mOutGlop->fill.filter.matrix.matrix;
memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
@@ -291,11 +290,12 @@ void GlopBuilder::setFill(int color, float alphaScale,
// Skia uses the range [0..255] for the addition vector, but we need
// the [0..1] range to apply the vector in GLSL
float* colorVector = mOutGlop->fill.filter.matrix.vector;
- colorVector[0] = EOCF(srcColorMatrix[4] / 255.0f);
- colorVector[1] = EOCF(srcColorMatrix[9] / 255.0f);
+ colorVector[0] = EOCF(srcColorMatrix[4] / 255.0f);
+ colorVector[1] = EOCF(srcColorMatrix[9] / 255.0f);
colorVector[2] = EOCF(srcColorMatrix[14] / 255.0f);
- colorVector[3] = srcColorMatrix[19] / 255.0f; // alpha is linear
+ colorVector[3] = srcColorMatrix[19] / 255.0f; // alpha is linear
} else {
+ ALOGE("unsupported ColorFilter type: %s", colorFilter->getTypeName());
LOG_ALWAYS_FATAL("unsupported ColorFilter");
}
} else {
@@ -303,14 +303,15 @@ void GlopBuilder::setFill(int color, float alphaScale,
}
}
-GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture,
- const int textureFillFlags, const SkPaint* paint, float alphaScale) {
+GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, const int textureFillFlags,
+ const SkPaint* paint, float alphaScale) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
GLenum filter = (textureFillFlags & TextureFillFlags::ForceFilter)
- ? GL_LINEAR : PaintUtils::getFilter(paint);
- mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, nullptr };
+ ? GL_LINEAR
+ : PaintUtils::getFilter(paint);
+ mOutGlop->fill.texture = {&texture, filter, GL_CLAMP_TO_EDGE, nullptr};
if (paint) {
int color = paint->getColor();
@@ -321,20 +322,17 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture,
color |= 0x00FFFFFF;
shader = nullptr;
}
- setFill(color, alphaScale,
- paint->getBlendMode(), Blend::ModeOrderSwap::NoSwap,
- shader, paint->getColorFilter());
+ setFill(color, alphaScale, paint->getBlendMode(), Blend::ModeOrderSwap::NoSwap, shader,
+ paint->getColorFilter());
} else {
- mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };
+ mOutGlop->fill.color = {alphaScale, alphaScale, alphaScale, alphaScale};
- if (alphaScale < 1.0f
- || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
- || texture.blend
- || mOutGlop->roundRectClipState) {
+ if (alphaScale < 1.0f || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha) ||
+ texture.blend || mOutGlop->roundRectClipState) {
Blend::getFactors(SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
- &mOutGlop->blend.src, &mOutGlop->blend.dst);
+ &mOutGlop->blend.src, &mOutGlop->blend.dst);
} else {
- mOutGlop->blend = { GL_ZERO, GL_ZERO };
+ mOutGlop->blend = {GL_ZERO, GL_ZERO};
}
}
@@ -352,32 +350,28 @@ GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale, b
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
if (CC_LIKELY(!shadowInterp)) {
- mOutGlop->fill.texture = {
- nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
+ mOutGlop->fill.texture = {nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr};
} else {
- mOutGlop->fill.texture = {
- mCaches.textureState().getShadowLutTexture(),
- GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
+ mOutGlop->fill.texture = {mCaches.textureState().getShadowLutTexture(), GL_INVALID_ENUM,
+ GL_INVALID_ENUM, nullptr};
}
- setFill(paint.getColor(), alphaScale,
- paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
+ setFill(paint.getColor(), alphaScale, paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
paint.getShader(), paint.getColorFilter());
mDescription.useShadowAlphaInterp = shadowInterp;
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
return *this;
}
-GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
- const SkPaint& paint, float alphaScale) {
+GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture, const SkPaint& paint,
+ float alphaScale) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
- //specify invalid filter/clamp, since these are always static for PathTextures
- mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
+ // specify invalid filter/clamp, since these are always static for PathTextures
+ mOutGlop->fill.texture = {&texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr};
- setFill(paint.getColor(), alphaScale,
- paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
+ setFill(paint.getColor(), alphaScale, paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
paint.getShader(), paint.getColorFilter());
mDescription.hasAlpha8Texture = true;
@@ -386,12 +380,12 @@ GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
}
GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
- const SkPaint& paint, float alphaScale) {
+ const SkPaint& paint, float alphaScale) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
- //specify invalid filter/clamp, since these are always static for ShadowTextures
- mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
+ // specify invalid filter/clamp, since these are always static for ShadowTextures
+ mOutGlop->fill.texture = {&texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr};
const int ALPHA_BITMASK = SK_ColorBLACK;
const int COLOR_BITMASK = ~ALPHA_BITMASK;
@@ -400,8 +394,7 @@ GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int
shadowColor &= paint.getColor() | COLOR_BITMASK;
}
- setFill(shadowColor, alphaScale,
- paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
+ setFill(shadowColor, alphaScale, paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
paint.getShader(), paint.getColorFilter());
mDescription.hasAlpha8Texture = true;
@@ -413,9 +406,9 @@ GlopBuilder& GlopBuilder::setFillBlack() {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
- mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
- setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
- nullptr, nullptr);
+ mOutGlop->fill.texture = {nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr};
+ setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap, nullptr,
+ nullptr);
return *this;
}
@@ -423,18 +416,19 @@ GlopBuilder& GlopBuilder::setFillClear() {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
- mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
- setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kClear, Blend::ModeOrderSwap::NoSwap,
- nullptr, nullptr);
+ mOutGlop->fill.texture = {nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr};
+ setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kClear, Blend::ModeOrderSwap::NoSwap, nullptr,
+ nullptr);
return *this;
}
GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
- float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage) {
+ float alpha, SkBlendMode mode,
+ Blend::ModeOrderSwap modeUsage) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
- mOutGlop->fill.texture = { &texture, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };
+ mOutGlop->fill.texture = {&texture, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr};
setFill(SK_ColorWHITE, alpha, mode, modeUsage, nullptr, colorFilter);
@@ -446,11 +440,11 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
- mOutGlop->fill.texture = { &(layer.getTexture()),
- GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };
+ mOutGlop->fill.texture = {&(layer.getTexture()), GL_LINEAR, GL_CLAMP_TO_EDGE,
+ &layer.getTexTransform()};
- setFill(SK_ColorWHITE, alpha, layer.getMode(), Blend::ModeOrderSwap::NoSwap,
- nullptr, layer.getColorFilter());
+ setFill(SK_ColorWHITE, alpha, layer.getMode(), Blend::ModeOrderSwap::NoSwap, nullptr,
+ layer.getColorFilter());
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
mDescription.hasTextureTransform = true;
@@ -458,15 +452,14 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) {
}
GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& textureTransform,
- bool requiresFilter) {
+ bool requiresFilter) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
GLenum filter = requiresFilter ? GL_LINEAR : GL_NEAREST;
- mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, &textureTransform };
+ mOutGlop->fill.texture = {&texture, filter, GL_CLAMP_TO_EDGE, &textureTransform};
- setFill(SK_ColorWHITE, 1.0f, SkBlendMode::kSrc, Blend::ModeOrderSwap::NoSwap,
- nullptr, nullptr);
+ setFill(SK_ColorWHITE, 1.0f, SkBlendMode::kSrc, Blend::ModeOrderSwap::NoSwap, nullptr, nullptr);
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
mDescription.hasTextureTransform = true;
@@ -517,8 +510,8 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination)
const float translateX = meshTransform.getTranslateX();
const float translateY = meshTransform.getTranslateY();
- left = (int) floorf(left + translateX + 0.5f) - translateX;
- top = (int) floorf(top + translateY + 0.5f) - translateY;
+ left = (int)floorf(left + translateX + 0.5f) - translateX;
+ top = (int)floorf(top + translateY + 0.5f) - translateY;
mOutGlop->fill.texture.filter = GL_NEAREST;
}
@@ -534,7 +527,8 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, c
return *this;
}
-GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offsetY, const Rect source) {
+GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offsetY,
+ const Rect source) {
TRIGGER_STAGE(kModelViewStage);
REQUIRE_STAGES(kTransformStage | kFillStage);
@@ -544,8 +538,8 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offset
const float translateX = meshTransform.getTranslateX();
const float translateY = meshTransform.getTranslateY();
- offsetX = (int) floorf(offsetX + translateX + source.left + 0.5f) - translateX - source.left;
- offsetY = (int) floorf(offsetY + translateY + source.top + 0.5f) - translateY - source.top;
+ offsetX = (int)floorf(offsetX + translateX + source.left + 0.5f) - translateX - source.left;
+ offsetY = (int)floorf(offsetY + translateY + source.top + 0.5f) - translateY - source.top;
mOutGlop->fill.texture.filter = GL_NEAREST;
}
@@ -571,27 +565,25 @@ GlopBuilder& GlopBuilder::setRoundRectClipState(const RoundRectClipState* roundR
void verify(const ProgramDescription& description, const Glop& glop) {
if (glop.fill.texture.texture != nullptr) {
- LOG_ALWAYS_FATAL_IF(((description.hasTexture && description.hasExternalTexture)
- || (!description.hasTexture
- && !description.hasExternalTexture
- && !description.useShadowAlphaInterp)
- || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) == 0
- && !description.useShadowAlphaInterp)),
- "Texture %p, hT%d, hET %d, attribFlags %x",
- glop.fill.texture.texture,
+ LOG_ALWAYS_FATAL_IF(
+ ((description.hasTexture && description.hasExternalTexture) ||
+ (!description.hasTexture && !description.hasExternalTexture &&
+ !description.useShadowAlphaInterp) ||
+ ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) == 0 &&
+ !description.useShadowAlphaInterp)),
+ "Texture %p, hT%d, hET %d, attribFlags %x", glop.fill.texture.texture,
description.hasTexture, description.hasExternalTexture,
glop.mesh.vertices.attribFlags);
} else {
- LOG_ALWAYS_FATAL_IF((description.hasTexture
- || description.hasExternalTexture
- || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) != 0)),
- "No texture, hT%d, hET %d, attribFlags %x",
- description.hasTexture, description.hasExternalTexture,
- glop.mesh.vertices.attribFlags);
+ LOG_ALWAYS_FATAL_IF(
+ (description.hasTexture || description.hasExternalTexture ||
+ ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) != 0)),
+ "No texture, hT%d, hET %d, attribFlags %x", description.hasTexture,
+ description.hasExternalTexture, glop.mesh.vertices.attribFlags);
}
- if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
- && glop.mesh.vertices.bufferObject) {
+ if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::Alpha) &&
+ glop.mesh.vertices.bufferObject) {
LOG_ALWAYS_FATAL("VBO and alpha attributes are not currently compatible");
}
@@ -620,9 +612,10 @@ void GlopBuilder::build() {
// Enable debug highlight when what we're about to draw is tested against
// the stencil buffer and if stencil highlight debugging is on
- mDescription.hasDebugHighlight = !Properties::debugOverdraw
- && Properties::debugStencilClip == StencilClipDebug::ShowHighlight
- && mRenderState.stencil().isTestEnabled();
+ mDescription.hasDebugHighlight =
+ !Properties::debugOverdraw &&
+ Properties::debugStencilClip == StencilClipDebug::ShowHighlight &&
+ mRenderState.stencil().isTestEnabled();
// serialize shader info into ShaderData
GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;
@@ -639,15 +632,13 @@ void GlopBuilder::build() {
} else {
shaderMatrix = mOutGlop->transform.modelView;
}
- SkiaShader::store(mCaches, *mShader, shaderMatrix,
- &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
+ SkiaShader::store(mCaches, *mShader, shaderMatrix, &textureUnit, &mDescription,
+ &(mOutGlop->fill.skiaShaderData));
}
// duplicates ProgramCache's definition of color uniform presence
- const bool singleColor = !mDescription.hasTexture
- && !mDescription.hasExternalTexture
- && !mDescription.hasGradient
- && !mDescription.hasBitmap;
+ const bool singleColor = !mDescription.hasTexture && !mDescription.hasExternalTexture &&
+ !mDescription.hasGradient && !mDescription.hasBitmap;
mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor;
verify(mDescription, *mOutGlop);
@@ -660,31 +651,31 @@ void GlopBuilder::dump(const Glop& glop) {
ALOGD("Glop Mesh");
const Glop::Mesh& mesh = glop.mesh;
ALOGD(" primitive mode: %d", mesh.primitiveMode);
- ALOGD(" indices: buffer obj %x, indices %p", mesh.indices.bufferObject, mesh.indices.indices);
+ ALOGD(" indices: buffer obj %x, indices %p", mesh.indices.bufferObject,
+ mesh.indices.indices);
const Glop::Mesh::Vertices& vertices = glop.mesh.vertices;
ALOGD(" vertices: buffer obj %x, flags %x, pos %p, tex %p, clr %p, stride %d",
- vertices.bufferObject, vertices.attribFlags,
- vertices.position, vertices.texCoord, vertices.color, vertices.stride);
+ vertices.bufferObject, vertices.attribFlags, vertices.position, vertices.texCoord,
+ vertices.color, vertices.stride);
ALOGD(" element count: %d", mesh.elementCount);
ALOGD("Glop Fill");
const Glop::Fill& fill = glop.fill;
ALOGD(" program %p", fill.program);
if (fill.texture.texture) {
- ALOGD(" texture %p, target %d, filter %d, clamp %d",
- fill.texture.texture, fill.texture.texture->target(),
- fill.texture.filter, fill.texture.clamp);
+ ALOGD(" texture %p, target %d, filter %d, clamp %d", fill.texture.texture,
+ fill.texture.texture->target(), fill.texture.filter, fill.texture.clamp);
if (fill.texture.textureTransform) {
fill.texture.textureTransform->dump("texture transform");
}
}
- ALOGD_IF(fill.colorEnabled, " color (argb) %.2f %.2f %.2f %.2f",
- fill.color.a, fill.color.r, fill.color.g, fill.color.b);
- ALOGD_IF(fill.filterMode != ProgramDescription::ColorFilterMode::None,
- " filterMode %d", (int)fill.filterMode);
+ ALOGD_IF(fill.colorEnabled, " color (argb) %.2f %.2f %.2f %.2f", fill.color.a, fill.color.r,
+ fill.color.g, fill.color.b);
+ ALOGD_IF(fill.filterMode != ProgramDescription::ColorFilterMode::None, " filterMode %d",
+ (int)fill.filterMode);
ALOGD_IF(fill.skiaShaderData.skiaShaderType, " shader type %d",
- fill.skiaShaderData.skiaShaderType);
+ fill.skiaShaderData.skiaShaderType);
ALOGD("Glop transform");
glop.transform.modelView.dump(" model view");
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 6d11da19e138..dac38223b877 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -39,15 +39,16 @@ struct PathTexture;
struct ShadowTexture;
namespace TextureFillFlags {
- enum {
- None = 0,
- IsAlphaMaskTexture = 1 << 0,
- ForceFilter = 1 << 1,
- };
+enum {
+ None = 0,
+ IsAlphaMaskTexture = 1 << 0,
+ ForceFilter = 1 << 1,
+};
}
class GlopBuilder {
PREVENT_COPY_AND_ASSIGN(GlopBuilder);
+
public:
GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop);
@@ -57,26 +58,29 @@ public:
GlopBuilder& setMeshTexturedUvQuad(const UvMapper* uvMapper, const Rect uvs);
GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer);
GlopBuilder& setMeshIndexedQuads(Vertex* vertexData, int quadCount);
- GlopBuilder& setMeshColoredTexturedMesh(ColorTextureVertex* vertexData, int elementCount); // TODO: use indexed quads
- GlopBuilder& setMeshTexturedIndexedQuads(TextureVertex* vertexData, int elementCount); // TODO: take quadCount
+ GlopBuilder& setMeshColoredTexturedMesh(ColorTextureVertex* vertexData,
+ int elementCount); // TODO: use indexed quads
+ GlopBuilder& setMeshTexturedIndexedQuads(TextureVertex* vertexData,
+ int elementCount); // TODO: take quadCount
GlopBuilder& setMeshPatchQuads(const Patch& patch);
- GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale, bool shadowInterp = false); // TODO: avoid boolean with default
+ GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale,
+ bool shadowInterp = false); // TODO: avoid boolean with default
GlopBuilder& setFillTexturePaint(Texture& texture, const int textureFillFlags,
- const SkPaint* paint, float alphaScale);
- GlopBuilder& setFillPathTexturePaint(PathTexture& texture,
- const SkPaint& paint, float alphaScale);
+ const SkPaint* paint, float alphaScale);
+ GlopBuilder& setFillPathTexturePaint(PathTexture& texture, const SkPaint& paint,
+ float alphaScale);
GlopBuilder& setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
- const SkPaint& paint, float alphaScale);
+ const SkPaint& paint, float alphaScale);
GlopBuilder& setFillBlack();
GlopBuilder& setFillClear();
- GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
- float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage);
+ GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter, float alpha,
+ SkBlendMode mode, Blend::ModeOrderSwap modeUsage);
GlopBuilder& setFillTextureLayer(GlLayer& layer, float alpha);
// TODO: setFillLayer normally forces its own wrap & filter mode,
// which isn't always correct.
GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform,
- bool requiresFilter);
+ bool requiresFilter);
GlopBuilder& setTransform(const Matrix4& canvas, const int transformFlags);
@@ -91,8 +95,8 @@ public:
}
GlopBuilder& setModelViewOffsetRect(float offsetX, float offsetY, const Rect source);
GlopBuilder& setModelViewOffsetRectSnap(float offsetX, float offsetY, const Rect source);
- GlopBuilder& setModelViewOffsetRectOptionalSnap(bool snap,
- float offsetX, float offsetY, const Rect& source) {
+ GlopBuilder& setModelViewOffsetRectOptionalSnap(bool snap, float offsetX, float offsetY,
+ const Rect& source) {
if (snap) {
return setModelViewOffsetRectSnap(offsetX, offsetY, source);
} else {
@@ -111,10 +115,10 @@ public:
void build();
static void dump(const Glop& glop);
+
private:
- void setFill(int color, float alphaScale,
- SkBlendMode mode, Blend::ModeOrderSwap modeUsage,
- const SkShader* shader, const SkColorFilter* colorFilter);
+ void setFill(int color, float alphaScale, SkBlendMode mode, Blend::ModeOrderSwap modeUsage,
+ const SkShader* shader, const SkColorFilter* colorFilter);
enum StageFlags {
kInitialStage = 0,
@@ -123,7 +127,8 @@ private:
kModelViewStage = 1 << 2,
kFillStage = 1 << 3,
kRoundRectClipStage = 1 << 4,
- kAllStages = kMeshStage | kFillStage | kTransformStage | kModelViewStage | kRoundRectClipStage,
+ kAllStages =
+ kMeshStage | kFillStage | kTransformStage | kModelViewStage | kRoundRectClipStage,
} mStageFlags;
ProgramDescription mDescription;
diff --git a/libs/hwui/GpuMemoryTracker.cpp b/libs/hwui/GpuMemoryTracker.cpp
index a52ec8738015..612bfde1a3fa 100644
--- a/libs/hwui/GpuMemoryTracker.cpp
+++ b/libs/hwui/GpuMemoryTracker.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "utils/StringUtils.h"
#include "Texture.h"
+#include "utils/StringUtils.h"
-#include <cutils/compiler.h>
#include <GpuMemoryTracker.h>
+#include <cutils/compiler.h>
#include <utils/Trace.h>
#include <array>
#include <sstream>
@@ -33,9 +33,7 @@ pthread_t gGpuThread = 0;
#define NUM_TYPES static_cast<int>(GpuObjectType::TypeCount)
const char* TYPE_NAMES[] = {
- "Texture",
- "OffscreenBuffer",
- "Layer",
+ "Texture", "OffscreenBuffer", "Layer",
};
struct TypeStats {
@@ -55,21 +53,22 @@ void GpuMemoryTracker::notifySizeChanged(int newSize) {
void GpuMemoryTracker::startTrackingObject() {
auto result = gObjectSet.insert(this);
LOG_ALWAYS_FATAL_IF(!result.second,
- "startTrackingObject() on %p failed, already being tracked!", this);
+ "startTrackingObject() on %p failed, already being tracked!", this);
gObjectStats[static_cast<int>(mType)].count++;
}
void GpuMemoryTracker::stopTrackingObject() {
size_t removed = gObjectSet.erase(this);
- LOG_ALWAYS_FATAL_IF(removed != 1,
- "stopTrackingObject removed %zd, is %p not being tracked?",
- removed, this);
+ LOG_ALWAYS_FATAL_IF(removed != 1, "stopTrackingObject removed %zd, is %p not being tracked?",
+ removed, this);
gObjectStats[static_cast<int>(mType)].count--;
}
void GpuMemoryTracker::onGpuContextCreated() {
- LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a gpu thread? "
- "current = %lu, gpu thread = %lu", pthread_self(), gGpuThread);
+ LOG_ALWAYS_FATAL_IF(gGpuThread != 0,
+ "We already have a gpu thread? "
+ "current = %lu, gpu thread = %lu",
+ pthread_self(), gGpuThread);
gGpuThread = pthread_self();
}
@@ -124,8 +123,8 @@ void GpuMemoryTracker::onFrameCompleted() {
if (obj->objectType() == GpuObjectType::Texture) {
const Texture* texture = static_cast<Texture*>(obj);
if (texture->cleanup) {
- ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u",
- texture->id(), texture->width(), texture->height());
+ ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u", texture->id(),
+ texture->width(), texture->height());
freeList.push_back(texture);
}
}
@@ -136,5 +135,5 @@ void GpuMemoryTracker::onFrameCompleted() {
}
}
-} // namespace uirenderer
-} // namespace android;
+} // namespace uirenderer
+} // namespace android;
diff --git a/libs/hwui/GpuMemoryTracker.h b/libs/hwui/GpuMemoryTracker.h
index 18e2330668b0..de3ca99ef14b 100644
--- a/libs/hwui/GpuMemoryTracker.h
+++ b/libs/hwui/GpuMemoryTracker.h
@@ -25,11 +25,11 @@ namespace uirenderer {
extern pthread_t gGpuThread;
-#define ASSERT_GPU_THREAD() LOG_ALWAYS_FATAL_IF( \
- !pthread_equal(gGpuThread, pthread_self()), \
- "Error, %p of type %d (size=%d) used on wrong thread! cur thread %lu " \
- "!= gpu thread %lu", this, static_cast<int>(mType), mSize, \
- pthread_self(), gGpuThread)
+#define ASSERT_GPU_THREAD() \
+ LOG_ALWAYS_FATAL_IF(!pthread_equal(gGpuThread, pthread_self()), \
+ "Error, %p of type %d (size=%d) used on wrong thread! cur thread %lu " \
+ "!= gpu thread %lu", \
+ this, static_cast<int>(mType), mSize, pthread_self(), gGpuThread)
enum class GpuObjectType {
Texture = 0,
@@ -73,5 +73,5 @@ private:
GpuObjectType mType;
};
-} // namespace uirenderer
-} // namespace android;
+} // namespace uirenderer
+} // namespace android;
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 20262349dda4..21e3c730cbec 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -18,9 +18,9 @@
#include "Caches.h"
#include "Debug.h"
+#include "DeviceInfo.h"
#include "GradientCache.h"
#include "Properties.h"
-#include "DeviceInfo.h"
#include <cutils/properties.h>
@@ -31,7 +31,7 @@ namespace uirenderer {
// Functions
///////////////////////////////////////////////////////////////////////////////
-template<typename T>
+template <typename T>
static inline T min(T a, T b) {
return a < b ? a : b;
}
@@ -122,8 +122,7 @@ void GradientCache::clear() {
mCache.clear();
}
-void GradientCache::getGradientInfo(const uint32_t* colors, const int count,
- GradientInfo& info) {
+void GradientCache::getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info) {
uint32_t width = 256 * (count - 1);
// If the npot extension is not supported we cannot use non-clamp
@@ -145,9 +144,8 @@ void GradientCache::getGradientInfo(const uint32_t* colors, const int count,
info.hasAlpha = hasAlpha;
}
-Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
- uint32_t* colors, float* positions, int count) {
-
+Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient, uint32_t* colors,
+ float* positions, int count) {
GradientInfo info;
getGradientInfo(colors, count, info);
@@ -159,18 +157,19 @@ Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
const uint32_t size = info.width * 2 * bytesPerPixel();
while (getSize() + size > mMaxSize) {
LOG_ALWAYS_FATAL_IF(!mCache.removeOldest(),
- "Ran out of things to remove from the cache? getSize() = %" PRIu32
- ", size = %" PRIu32 ", mMaxSize = %" PRIu32 ", width = %" PRIu32,
- getSize(), size, mMaxSize, info.width);
+ "Ran out of things to remove from the cache? getSize() = %" PRIu32
+ ", size = %" PRIu32 ", mMaxSize = %" PRIu32 ", width = %" PRIu32,
+ getSize(), size, mMaxSize, info.width);
}
generateTexture(colors, positions, info.width, 2, texture);
mSize += size;
LOG_ALWAYS_FATAL_IF((int)size != texture->objectSize(),
- "size != texture->objectSize(), size %" PRIu32 ", objectSize %d"
- " width = %" PRIu32 " bytesPerPixel() = %zu",
- size, texture->objectSize(), info.width, bytesPerPixel());
+ "size != texture->objectSize(), size %" PRIu32
+ ", objectSize %d"
+ " width = %" PRIu32 " bytesPerPixel() = %zu",
+ size, texture->objectSize(), info.width, bytesPerPixel());
mCache.put(gradient, texture);
return texture;
@@ -186,8 +185,8 @@ size_t GradientCache::sourceBytesPerPixel() const {
return 4 * (mUseFloatTexture ? sizeof(float) : sizeof(uint8_t));
}
-void GradientCache::mixBytes(const FloatColor& start, const FloatColor& end,
- float amount, uint8_t*& dst) const {
+void GradientCache::mixBytes(const FloatColor& start, const FloatColor& end, float amount,
+ uint8_t*& dst) const {
float oppAmount = 1.0f - amount;
float a = start.a * oppAmount + end.a * amount;
*dst++ = uint8_t(OECF(start.r * oppAmount + end.r * amount) * 255.0f);
@@ -196,11 +195,11 @@ void GradientCache::mixBytes(const FloatColor& start, const FloatColor& end,
*dst++ = uint8_t(a * 255.0f);
}
-void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end,
- float amount, uint8_t*& dst) const {
+void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end, float amount,
+ uint8_t*& dst) const {
float oppAmount = 1.0f - amount;
float a = start.a * oppAmount + end.a * amount;
- float* d = (float*) dst;
+ float* d = (float*)dst;
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
// We want to stay linear
*d++ = (start.r * oppAmount + end.r * amount);
@@ -215,8 +214,8 @@ void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end,
dst += 4 * sizeof(float);
}
-void GradientCache::generateTexture(uint32_t* colors, float* positions,
- const uint32_t width, const uint32_t height, Texture* texture) {
+void GradientCache::generateTexture(uint32_t* colors, float* positions, const uint32_t width,
+ const uint32_t height, Texture* texture) {
const GLsizei rowBytes = width * sourceBytesPerPixel();
uint8_t pixels[rowBytes * height];
@@ -269,5 +268,5 @@ void GradientCache::generateTexture(uint32_t* colors, float* positions,
texture->setWrap(GL_CLAMP_TO_EDGE);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index d95589c514eb..ff426cd3425b 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -60,13 +60,9 @@ struct GradientCacheEntry {
static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs);
- bool operator==(const GradientCacheEntry& other) const {
- return compare(*this, other) == 0;
- }
+ bool operator==(const GradientCacheEntry& other) const { return compare(*this, other) == 0; }
- bool operator!=(const GradientCacheEntry& other) const {
- return compare(*this, other) != 0;
- }
+ bool operator!=(const GradientCacheEntry& other) const { return compare(*this, other) != 0; }
std::unique_ptr<uint32_t[]> colors;
std::unique_ptr<float[]> positions;
@@ -82,7 +78,7 @@ private:
memcpy(this->positions.get(), positions, count * sizeof(float));
}
-}; // GradientCacheEntry
+}; // GradientCacheEntry
// Caching support
@@ -103,7 +99,7 @@ inline hash_t hash_type(const GradientCacheEntry& entry) {
* Any texture added to the cache causing the cache to grow beyond the maximum
* allowed size will also cause the oldest texture to be kicked out.
*/
-class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
+class GradientCache : public OnEntryRemoved<GradientCacheEntry, Texture*> {
public:
explicit GradientCache(const Extensions& extensions);
~GradientCache();
@@ -138,11 +134,11 @@ private:
* Adds a new linear gradient to the cache. The generated texture is
* returned.
*/
- Texture* addLinearGradient(GradientCacheEntry& gradient,
- uint32_t* colors, float* positions, int count);
+ Texture* addLinearGradient(GradientCacheEntry& gradient, uint32_t* colors, float* positions,
+ int count);
- void generateTexture(uint32_t* colors, float* positions,
- const uint32_t width, const uint32_t height, Texture* texture);
+ void generateTexture(uint32_t* colors, float* positions, const uint32_t width,
+ const uint32_t height, Texture* texture);
struct GradientInfo {
uint32_t width;
@@ -155,12 +151,12 @@ private:
size_t sourceBytesPerPixel() const;
typedef void (GradientCache::*ChannelMixer)(const FloatColor& start, const FloatColor& end,
- float amount, uint8_t*& dst) const;
+ float amount, uint8_t*& dst) const;
- void mixBytes(const FloatColor& start, const FloatColor& end,
- float amount, uint8_t*& dst) const;
- void mixFloats(const FloatColor& start, const FloatColor& end,
- float amount, uint8_t*& dst) const;
+ void mixBytes(const FloatColor& start, const FloatColor& end, float amount,
+ uint8_t*& dst) const;
+ void mixFloats(const FloatColor& start, const FloatColor& end, float amount,
+ uint8_t*& dst) const;
LruCache<GradientCacheEntry, Texture*> mCache;
@@ -173,9 +169,9 @@ private:
bool mHasLinearBlending;
mutable Mutex mLock;
-}; // class GradientCache
+}; // class GradientCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_GRADIENT_CACHE_H
+#endif // ANDROID_HWUI_GRADIENT_CACHE_H
diff --git a/libs/hwui/IProfileRenderer.h b/libs/hwui/IProfileRenderer.h
index 947ed34cc070..935ab4e35f26 100644
--- a/libs/hwui/IProfileRenderer.h
+++ b/libs/hwui/IProfileRenderer.h
@@ -22,7 +22,7 @@ namespace uirenderer {
class IProfileRenderer {
public:
virtual void drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) = 0;
+ const SkPaint& paint) = 0;
virtual void drawRects(const float* rects, int count, const SkPaint& paint) = 0;
virtual uint32_t getViewportWidth() = 0;
virtual uint32_t getViewportHeight() = 0;
diff --git a/libs/hwui/Image.cpp b/libs/hwui/Image.cpp
index 68a356ba1be0..d30796d01479 100644
--- a/libs/hwui/Image.cpp
+++ b/libs/hwui/Image.cpp
@@ -25,11 +25,11 @@ namespace uirenderer {
Image::Image(sp<GraphicBuffer> buffer) {
// Create the EGLImage object that maps the GraphicBuffer
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
- EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
+ EGLClientBuffer clientBuffer = (EGLClientBuffer)buffer->getNativeBuffer();
+ EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
- mImage = eglCreateImageKHR(display, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
+ mImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer,
+ attrs);
if (mImage == EGL_NO_IMAGE_KHR) {
ALOGW("Error creating image (%#x)", eglGetError());
@@ -57,5 +57,5 @@ Image::~Image() {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Image.h b/libs/hwui/Image.h
index b8f5a5bec087..989b6ff3648d 100644
--- a/libs/hwui/Image.h
+++ b/libs/hwui/Image.h
@@ -45,23 +45,19 @@ public:
* Returns the name of the GL texture that can be used to sample
* from this image.
*/
- GLuint getTexture() const {
- return mTexture;
- }
+ GLuint getTexture() const { return mTexture; }
/**
* Returns the name of the EGL image represented by this object.
*/
- EGLImageKHR getImage() const {
- return mImage;
- }
+ EGLImageKHR getImage() const { return mImage; }
private:
GLuint mTexture;
EGLImageKHR mImage;
-}; // class Image
+}; // class Image
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_IMAGE_H
+#endif // ANDROID_HWUI_IMAGE_H
diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp
index d740c038f36d..7bdca2ee0f00 100644
--- a/libs/hwui/Interpolator.cpp
+++ b/libs/hwui/Interpolator.cpp
@@ -54,8 +54,10 @@ static float o(float t, float s) {
}
float AnticipateOvershootInterpolator::interpolate(float t) {
- if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension);
- else return 0.5f * (o(t * 2.0f - 2.0f, mTension) + 2.0f);
+ if (t < 0.5f)
+ return 0.5f * a(t * 2.0f, mTension);
+ else
+ return 0.5f * (o(t * 2.0f - 2.0f, mTension) + 2.0f);
}
static float bounce(float t) {
@@ -64,10 +66,14 @@ static float bounce(float t) {
float BounceInterpolator::interpolate(float t) {
t *= 1.1226f;
- if (t < 0.3535f) return bounce(t);
- else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;
- else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
- else return bounce(t - 1.0435f) + 0.95f;
+ if (t < 0.3535f)
+ return bounce(t);
+ else if (t < 0.7408f)
+ return bounce(t - 0.54719f) + 0.7f;
+ else if (t < 0.9644f)
+ return bounce(t - 0.8526f) + 0.9f;
+ else
+ return bounce(t - 1.0435f) + 0.95f;
}
float CycleInterpolator::interpolate(float input) {
@@ -119,16 +125,11 @@ float PathInterpolator::interpolate(float t) {
float startY = mY[startIndex];
float endY = mY[endIndex];
return startY + (fraction * (endY - startY));
-
}
-LUTInterpolator::LUTInterpolator(float* values, size_t size)
- : mValues(values)
- , mSize(size) {
-}
+LUTInterpolator::LUTInterpolator(float* values, size_t size) : mValues(values), mSize(size) {}
-LUTInterpolator::~LUTInterpolator() {
-}
+LUTInterpolator::~LUTInterpolator() {}
float LUTInterpolator::interpolate(float input) {
// lut position should only be at the end of the table when input is 1f.
@@ -140,10 +141,12 @@ float LUTInterpolator::interpolate(float input) {
float ipart, weight;
weight = modff(lutpos, &ipart);
- int i1 = (int) ipart;
- int i2 = std::min(i1 + 1, (int) mSize - 1);
+ int i1 = (int)ipart;
+ int i2 = std::min(i1 + 1, (int)mSize - 1);
- LOG_ALWAYS_FATAL_IF(i1 < 0 || i2 < 0, "negatives in interpolation!"
+ LOG_ALWAYS_FATAL_IF(
+ i1 < 0 || i2 < 0,
+ "negatives in interpolation!"
" i1=%d, i2=%d, input=%f, lutpos=%f, size=%zu, values=%p, ipart=%f, weight=%f",
i1, i2, input, lutpos, mSize, mValues.get(), ipart, weight);
@@ -153,6 +156,5 @@ float LUTInterpolator::interpolate(float input) {
return MathUtils::lerp(v1, v2, weight);
}
-
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/Interpolator.h b/libs/hwui/Interpolator.h
index 224cee70acc7..452988fc8711 100644
--- a/libs/hwui/Interpolator.h
+++ b/libs/hwui/Interpolator.h
@@ -44,8 +44,9 @@ public:
class ANDROID_API AccelerateInterpolator : public Interpolator {
public:
- explicit AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor*2) {}
+ explicit AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor * 2) {}
virtual float interpolate(float input) override;
+
private:
const float mFactor;
const float mDoubleFactor;
@@ -55,6 +56,7 @@ class ANDROID_API AnticipateInterpolator : public Interpolator {
public:
explicit AnticipateInterpolator(float tension) : mTension(tension) {}
virtual float interpolate(float input) override;
+
private:
const float mTension;
};
@@ -63,6 +65,7 @@ class ANDROID_API AnticipateOvershootInterpolator : public Interpolator {
public:
explicit AnticipateOvershootInterpolator(float tension) : mTension(tension) {}
virtual float interpolate(float input) override;
+
private:
const float mTension;
};
@@ -76,6 +79,7 @@ class ANDROID_API CycleInterpolator : public Interpolator {
public:
explicit CycleInterpolator(float cycles) : mCycles(cycles) {}
virtual float interpolate(float input) override;
+
private:
const float mCycles;
};
@@ -84,6 +88,7 @@ class ANDROID_API DecelerateInterpolator : public Interpolator {
public:
explicit DecelerateInterpolator(float factor) : mFactor(factor) {}
virtual float interpolate(float input) override;
+
private:
const float mFactor;
};
@@ -97,15 +102,16 @@ class ANDROID_API OvershootInterpolator : public Interpolator {
public:
explicit OvershootInterpolator(float tension) : mTension(tension) {}
virtual float interpolate(float input) override;
+
private:
const float mTension;
};
class ANDROID_API PathInterpolator : public Interpolator {
public:
- explicit PathInterpolator(std::vector<float>&& x, std::vector<float>&& y)
- : mX (x), mY(y) {}
+ explicit PathInterpolator(std::vector<float>&& x, std::vector<float>&& y) : mX(x), mY(y) {}
virtual float interpolate(float input) override;
+
private:
std::vector<float> mX;
std::vector<float> mY;
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 9d1182819444..e6d2a6f555ac 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -27,24 +27,37 @@
#include <cutils/ashmem.h>
#include <log/log.h>
+#include <sstream>
#include "Properties.h"
#include "utils/TimeUtils.h"
+#include "utils/Trace.h"
namespace android {
namespace uirenderer {
struct Comparison {
+ JankType type;
+ std::function<int64_t(nsecs_t)> computeThreadshold;
FrameInfoIndex start;
FrameInfoIndex end;
};
-static const Comparison COMPARISONS[] = {
- {FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync},
- {FrameInfoIndex::OldestInputEvent, FrameInfoIndex::Vsync},
- {FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart},
- {FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart},
- {FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted},
+static const std::array<Comparison, 4> COMPARISONS{
+ Comparison{JankType::kMissedVsync, [](nsecs_t) { return 1; }, FrameInfoIndex::IntendedVsync,
+ FrameInfoIndex::Vsync},
+
+ Comparison{JankType::kSlowUI,
+ [](nsecs_t frameInterval) { return static_cast<int64_t>(.5 * frameInterval); },
+ FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart},
+
+ Comparison{JankType::kSlowSync,
+ [](nsecs_t frameInterval) { return static_cast<int64_t>(.2 * frameInterval); },
+ FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart},
+
+ Comparison{JankType::kSlowRT,
+ [](nsecs_t frameInterval) { return static_cast<int64_t>(.75 * frameInterval); },
+ FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted},
};
// If the event exceeds 10 seconds throw it away, this isn't a jank event
@@ -88,73 +101,91 @@ JankTracker::JankTracker(ProfileDataContainer* globalData, const DisplayInfo& di
void JankTracker::setFrameInterval(nsecs_t frameInterval) {
mFrameInterval = frameInterval;
- mThresholds[kMissedVsync] = 1;
- /*
- * Due to interpolation and sample rate differences between the touch
- * panel and the display (example, 85hz touch panel driving a 60hz display)
- * we call high latency 1.5 * frameinterval
- *
- * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel
- * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms
- * Thus this must always be larger than frameInterval, or it will fail
- */
- mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval);
-
- // Note that these do not add up to 1. This is intentional. It's to deal
- // with variance in values, and should be sort of an upper-bound on what
- // is reasonable to expect.
- mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval);
- mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval);
- mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval);
+ for (auto& comparison : COMPARISONS) {
+ mThresholds[comparison.type] = comparison.computeThreadshold(frameInterval);
+ }
}
void JankTracker::finishFrame(const FrameInfo& frame) {
// Fast-path for jank-free frames
int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted);
- if (mDequeueTimeForgiveness
- && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) {
- nsecs_t expectedDequeueDuration =
- mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync]
- - frame[FrameInfoIndex::IssueDrawCommandsStart];
+ if (mDequeueTimeForgiveness && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) {
+ nsecs_t expectedDequeueDuration = mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync] -
+ frame[FrameInfoIndex::IssueDrawCommandsStart];
if (expectedDequeueDuration > 0) {
// Forgive only up to the expected amount, but not more than
// the actual time spent blocked.
- nsecs_t forgiveAmount = std::min(expectedDequeueDuration,
- frame[FrameInfoIndex::DequeueBufferDuration]);
+ nsecs_t forgiveAmount =
+ std::min(expectedDequeueDuration, frame[FrameInfoIndex::DequeueBufferDuration]);
LOG_ALWAYS_FATAL_IF(forgiveAmount >= totalDuration,
- "Impossible dequeue duration! dequeue duration reported %" PRId64
- ", total duration %" PRId64, forgiveAmount, totalDuration);
+ "Impossible dequeue duration! dequeue duration reported %" PRId64
+ ", total duration %" PRId64,
+ forgiveAmount, totalDuration);
totalDuration -= forgiveAmount;
}
}
+
LOG_ALWAYS_FATAL_IF(totalDuration <= 0, "Impossible totalDuration %" PRId64, totalDuration);
mData->reportFrame(totalDuration);
(*mGlobalData)->reportFrame(totalDuration);
- // Keep the fast path as fast as possible.
- if (CC_LIKELY(totalDuration < mFrameInterval)) {
+ // Only things like Surface.lockHardwareCanvas() are exempt from tracking
+ if (CC_UNLIKELY(frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS)) {
return;
}
- // Only things like Surface.lockHardwareCanvas() are exempt from tracking
- if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) {
+ if (totalDuration > mFrameInterval) {
+ mData->reportJank();
+ (*mGlobalData)->reportJank();
+ }
+
+ bool isTripleBuffered = mSwapDeadline > frame[FrameInfoIndex::IntendedVsync];
+
+ mSwapDeadline = std::max(mSwapDeadline + mFrameInterval,
+ frame[FrameInfoIndex::IntendedVsync] + mFrameInterval);
+
+ // If we hit the deadline, cool!
+ if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline) {
+ if (isTripleBuffered) {
+ mData->reportJankType(JankType::kHighInputLatency);
+ (*mGlobalData)->reportJankType(JankType::kHighInputLatency);
+ }
return;
}
- mData->reportJank();
- (*mGlobalData)->reportJank();
+ mData->reportJankType(JankType::kMissedDeadline);
+ (*mGlobalData)->reportJankType(JankType::kMissedDeadline);
+
+ // Janked, reset the swap deadline
+ nsecs_t jitterNanos = frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::Vsync];
+ nsecs_t lastFrameOffset = jitterNanos % mFrameInterval;
+ mSwapDeadline = frame[FrameInfoIndex::FrameCompleted] - lastFrameOffset + mFrameInterval;
+
+ for (auto& comparison : COMPARISONS) {
+ int64_t delta = frame.duration(comparison.start, comparison.end);
+ if (delta >= mThresholds[comparison.type] && delta < IGNORE_EXCEEDING) {
+ mData->reportJankType(comparison.type);
+ (*mGlobalData)->reportJankType(comparison.type);
+ }
+ }
- for (int i = 0; i < NUM_BUCKETS; i++) {
- int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end);
- if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
- mData->reportJankType((JankType) i);
- (*mGlobalData)->reportJankType((JankType) i);
+ // Log daveys since they are weird and we don't know what they are (b/70339576)
+ if (totalDuration >= 700_ms) {
+ static int sDaveyCount = 0;
+ std::stringstream ss;
+ ss << "Davey! duration=" << ns2ms(totalDuration) << "ms; ";
+ for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
+ ss << FrameInfoNames[i] << "=" << frame[i] << ", ";
}
+ ALOGI("%s", ss.str().c_str());
+ // Just so we have something that counts up, the value is largely irrelevant
+ ATRACE_INT(ss.str().c_str(), ++sDaveyCount);
}
}
-void JankTracker::dumpData(int fd, const ProfileDataDescription* description, const ProfileData* data) {
+void JankTracker::dumpData(int fd, const ProfileDataDescription* description,
+ const ProfileData* data) {
if (description) {
switch (description->type) {
case JankTrackerType::Generic:
@@ -175,33 +206,30 @@ void JankTracker::dumpData(int fd, const ProfileDataDescription* description, co
}
void JankTracker::dumpFrames(int fd) {
- FILE* file = fdopen(fd, "a");
- fprintf(file, "\n\n---PROFILEDATA---\n");
+ dprintf(fd, "\n\n---PROFILEDATA---\n");
for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
- fprintf(file, "%s", FrameInfoNames[i].c_str());
- fprintf(file, ",");
+ dprintf(fd, "%s", FrameInfoNames[i].c_str());
+ dprintf(fd, ",");
}
for (size_t i = 0; i < mFrames.size(); i++) {
FrameInfo& frame = mFrames[i];
if (frame[FrameInfoIndex::SyncStart] == 0) {
continue;
}
- fprintf(file, "\n");
+ dprintf(fd, "\n");
for (int i = 0; i < static_cast<int>(FrameInfoIndex::NumIndexes); i++) {
- fprintf(file, "%" PRId64 ",", frame[i]);
+ dprintf(fd, "%" PRId64 ",", frame[i]);
}
}
- fprintf(file, "\n---PROFILEDATA---\n\n");
- fflush(file);
+ dprintf(fd, "\n---PROFILEDATA---\n\n");
}
void JankTracker::reset() {
mFrames.clear();
mData->reset();
(*mGlobalData)->reset();
- sFrameStart = Properties::filterOutTestOverhead
- ? FrameInfoIndex::HandleInputStart
- : FrameInfoIndex::IntendedVsync;
+ sFrameStart = Properties::filterOutTestOverhead ? FrameInfoIndex::HandleInputStart
+ : FrameInfoIndex::IntendedVsync;
}
} /* namespace uirenderer */
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index e56c0791d3a4..110211eda23a 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -70,10 +70,12 @@ public:
private:
void setFrameInterval(nsecs_t frameIntervalNanos);
- static void dumpData(int fd, const ProfileDataDescription* description, const ProfileData* data);
+ static void dumpData(int fd, const ProfileDataDescription* description,
+ const ProfileData* data);
std::array<int64_t, NUM_BUCKETS> mThresholds;
int64_t mFrameInterval;
+ nsecs_t mSwapDeadline;
// The amount of time we will erase from the total duration to account
// for SF vsync offsets with HWC2 blocking dequeueBuffers.
// (Vsync + mDequeueBlockTolerance) is the point at which we expect
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index b58dfce787ef..fb8f0337c95e 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -18,39 +18,63 @@
#include "renderstate/RenderState.h"
-#include <SkColorFilter.h>
+#include <SkToSRGBColorFilter.h>
namespace android {
namespace uirenderer {
-Layer::Layer(RenderState& renderState, Api api, SkColorFilter* colorFilter, int alpha,
- SkBlendMode mode)
+Layer::Layer(RenderState& renderState, Api api, sk_sp<SkColorFilter> colorFilter, int alpha,
+ SkBlendMode mode)
: GpuMemoryTracker(GpuObjectType::Layer)
, mRenderState(renderState)
, mApi(api)
- , colorFilter(nullptr)
+ , mColorFilter(colorFilter)
, alpha(alpha)
, mode(mode) {
// TODO: This is a violation of Android's typical ref counting, but it
// preserves the old inc/dec ref locations. This should be changed...
incStrong(nullptr);
-
+ buildColorSpaceWithFilter();
renderState.registerLayer(this);
}
Layer::~Layer() {
- SkSafeUnref(colorFilter);
-
mRenderState.unregisterLayer(this);
}
-void Layer::setColorFilter(SkColorFilter* filter) {
- SkRefCnt_SafeAssign(colorFilter, filter);
+void Layer::setColorFilter(sk_sp<SkColorFilter> filter) {
+ if (filter != mColorFilter) {
+ mColorFilter = filter;
+ buildColorSpaceWithFilter();
+ }
+}
+
+void Layer::setDataSpace(android_dataspace dataspace) {
+ if (dataspace != mCurrentDataspace) {
+ mCurrentDataspace = dataspace;
+ buildColorSpaceWithFilter();
+ }
+}
+
+void Layer::buildColorSpaceWithFilter() {
+ sk_sp<SkColorFilter> colorSpaceFilter;
+ sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace(mCurrentDataspace);
+ if (colorSpace && !colorSpace->isSRGB()) {
+ colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
+ }
+
+ if (mColorFilter && colorSpaceFilter) {
+ mColorSpaceWithFilter = mColorFilter->makeComposed(colorSpaceFilter);
+ } else if (colorSpaceFilter) {
+ mColorSpaceWithFilter = colorSpaceFilter;
+ } else {
+ mColorSpaceWithFilter = mColorFilter;
+ }
}
void Layer::postDecStrong() {
mRenderState.postDecStrong(this);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index e5520ea0e811..89bcddcc96d0 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -16,11 +16,13 @@
#pragma once
-#include <utils/RefBase.h>
#include <GpuMemoryTracker.h>
+#include <utils/RefBase.h>
-#include <SkPaint.h>
+#include <SkColorFilter.h>
+#include <SkColorSpace.h>
#include <SkBlendMode.h>
+#include <SkPaint.h>
#include "Matrix.h"
@@ -43,9 +45,7 @@ public:
Vulkan = 1,
};
- Api getApi() const {
- return mApi;
- }
+ Api getApi() const { return mApi; }
~Layer();
@@ -59,44 +59,34 @@ public:
virtual bool isBlend() const = 0;
- inline void setForceFilter(bool forceFilter) {
- this->forceFilter = forceFilter;
- }
+ inline void setForceFilter(bool forceFilter) { this->forceFilter = forceFilter; }
- inline bool getForceFilter() const {
- return forceFilter;
- }
+ inline bool getForceFilter() const { return forceFilter; }
- inline void setAlpha(int alpha) {
- this->alpha = alpha;
- }
+ inline void setAlpha(int alpha) { this->alpha = alpha; }
inline void setAlpha(int alpha, SkBlendMode mode) {
this->alpha = alpha;
this->mode = mode;
}
- inline int getAlpha() const {
- return alpha;
- }
+ inline int getAlpha() const { return alpha; }
- inline SkBlendMode getMode() const {
- return mode;
- }
+ inline SkBlendMode getMode() const { return mode; }
- inline SkColorFilter* getColorFilter() const {
- return colorFilter;
- }
+ inline SkColorFilter* getColorFilter() const { return mColorFilter.get(); }
- void setColorFilter(SkColorFilter* filter);
+ void setColorFilter(sk_sp<SkColorFilter> filter);
- inline mat4& getTexTransform() {
- return texTransform;
- }
+ void setDataSpace(android_dataspace dataspace);
- inline mat4& getTransform() {
- return transform;
- }
+ void setColorSpace(sk_sp<SkColorSpace> colorSpace);
+
+ inline sk_sp<SkColorFilter> getColorSpaceWithFilter() const { return mColorSpaceWithFilter; }
+
+ inline mat4& getTexTransform() { return texTransform; }
+
+ inline mat4& getTransform() { return transform; }
/**
* Posts a decStrong call to the appropriate thread.
@@ -105,18 +95,30 @@ public:
void postDecStrong();
protected:
- Layer(RenderState& renderState, Api api, SkColorFilter* colorFilter, int alpha,
- SkBlendMode mode);
+ Layer(RenderState& renderState, Api api, sk_sp<SkColorFilter>, int alpha,
+ SkBlendMode mode);
RenderState& mRenderState;
private:
+ void buildColorSpaceWithFilter();
+
Api mApi;
/**
* Color filter used to draw this layer. Optional.
*/
- SkColorFilter* colorFilter;
+ sk_sp<SkColorFilter> mColorFilter;
+
+ /**
+ * Colorspace of the contents of the layer. Optional.
+ */
+ android_dataspace mCurrentDataspace = HAL_DATASPACE_UNKNOWN;
+
+ /**
+ * A color filter that is the combination of the mColorFilter and mColorSpace. Optional.
+ */
+ sk_sp<SkColorFilter> mColorSpaceWithFilter;
/**
* Indicates raster data backing the layer is scaled, requiring filtration.
@@ -143,7 +145,7 @@ private:
*/
mat4 transform;
-}; // struct Layer
+}; // struct Layer
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index c5d5492d4fd1..15ede4ca148a 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -29,8 +29,7 @@ namespace uirenderer {
class BatchBase {
public:
BatchBase(batchid_t batchId, BakedOpState* op, bool merging)
- : mBatchId(batchId)
- , mMerging(merging) {
+ : mBatchId(batchId), mMerging(merging) {
mBounds = op->computedState.clippedBounds;
mOps.push_back(op);
}
@@ -52,9 +51,10 @@ public:
const std::vector<BakedOpState*>& getOps() const { return mOps; }
void dump() const {
- ALOGD(" Batch %p, id %d, merging %d, count %d, bounds " RECT_STRING,
- this, mBatchId, mMerging, (int) mOps.size(), RECT_ARGS(mBounds));
+ ALOGD(" Batch %p, id %d, merging %d, count %d, bounds " RECT_STRING, this, mBatchId,
+ mMerging, (int)mOps.size(), RECT_ARGS(mBounds));
}
+
protected:
batchid_t mBatchId;
Rect mBounds;
@@ -64,9 +64,7 @@ protected:
class OpBatch : public BatchBase {
public:
- OpBatch(batchid_t batchId, BakedOpState* op)
- : BatchBase(batchId, op, false) {
- }
+ OpBatch(batchid_t batchId, BakedOpState* op) : BatchBase(batchId, op, false) {}
void batchOp(BakedOpState* op) {
mBounds.unionWith(op->computedState.clippedBounds);
@@ -77,16 +75,14 @@ public:
class MergingOpBatch : public BatchBase {
public:
MergingOpBatch(batchid_t batchId, BakedOpState* op)
- : BatchBase(batchId, op, true)
- , mClipSideFlags(op->computedState.clipSideFlags) {
- }
+ : BatchBase(batchId, op, true), mClipSideFlags(op->computedState.clipSideFlags) {}
/*
* Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds
* and clip side flags. Positive bounds delta means new bounds fit in old.
*/
static inline bool checkSide(const int currentFlags, const int newFlags, const int side,
- float boundsDelta) {
+ float boundsDelta) {
bool currentClipExists = currentFlags & side;
bool newClipExists = newFlags & side;
@@ -100,16 +96,14 @@ public:
}
static bool paintIsDefault(const SkPaint& paint) {
- return paint.getAlpha() == 255
- && paint.getColorFilter() == nullptr
- && paint.getShader() == nullptr;
+ return paint.getAlpha() == 255 && paint.getColorFilter() == nullptr &&
+ paint.getShader() == nullptr;
}
static bool paintsAreEquivalent(const SkPaint& a, const SkPaint& b) {
// Note: don't check color, since all currently mergeable ops can merge across colors
- return a.getAlpha() == b.getAlpha()
- && a.getColorFilter() == b.getColorFilter()
- && a.getShader() == b.getShader();
+ return a.getAlpha() == b.getAlpha() && a.getColorFilter() == b.getColorFilter() &&
+ a.getShader() == b.getShader();
}
/*
@@ -123,8 +117,8 @@ public:
* dropped, so we make simplifying qualifications on the ops that can merge, per op type.
*/
bool canMergeWith(BakedOpState* op) const {
- bool isTextBatch = getBatchId() == OpBatchType::Text
- || getBatchId() == OpBatchType::ColorText;
+ bool isTextBatch =
+ getBatchId() == OpBatchType::Text || getBatchId() == OpBatchType::ColorText;
// Overlapping other operations is only allowed for text without shadow. For other ops,
// multiDraw isn't guaranteed to overdraw correctly
@@ -142,8 +136,9 @@ public:
if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
// Local masks prevent merge, since they're potentially in different coordinate spaces
- if (lhs->computedState.localProjectionPathMask
- || rhs->computedState.localProjectionPathMask) return false;
+ if (lhs->computedState.localProjectionPathMask ||
+ rhs->computedState.localProjectionPathMask)
+ return false;
/* Clipping compatibility check
*
@@ -155,15 +150,18 @@ public:
if (currentFlags != OpClipSideFlags::None || newFlags != OpClipSideFlags::None) {
const Rect& opBounds = op->computedState.clippedBounds;
float boundsDelta = mBounds.left - opBounds.left;
- if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Left, boundsDelta)) return false;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Left, boundsDelta))
+ return false;
boundsDelta = mBounds.top - opBounds.top;
if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Top, boundsDelta)) return false;
// right and bottom delta calculation reversed to account for direction
boundsDelta = opBounds.right - mBounds.right;
- if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Right, boundsDelta)) return false;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Right, boundsDelta))
+ return false;
boundsDelta = opBounds.bottom - mBounds.bottom;
- if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Bottom, boundsDelta)) return false;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Bottom, boundsDelta))
+ return false;
}
const SkPaint* newPaint = op->op->paint;
@@ -197,8 +195,8 @@ private:
int mClipSideFlags;
};
-LayerBuilder::LayerBuilder(uint32_t width, uint32_t height,
- const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode)
+LayerBuilder::LayerBuilder(uint32_t width, uint32_t height, const Rect& repaintRect,
+ const BeginLayerOp* beginLayerOp, RenderNode* renderNode)
: width(width)
, height(height)
, repaintRect(repaintRect)
@@ -210,7 +208,7 @@ LayerBuilder::LayerBuilder(uint32_t width, uint32_t height,
// iterate back toward target to see if anything drawn since should overlap the new op
// if no target, merging ops still iterate to find similar batch to insert after
void LayerBuilder::locateInsertIndex(int batchId, const Rect& clippedBounds,
- BatchBase** targetBatch, size_t* insertBatchIndex) const {
+ BatchBase** targetBatch, size_t* insertBatchIndex) const {
for (int i = mBatches.size() - 1; i >= 0; i--) {
BatchBase* overBatch = mBatches[i];
@@ -219,7 +217,7 @@ void LayerBuilder::locateInsertIndex(int batchId, const Rect& clippedBounds,
// TODO: also consider shader shared between batch types
if (batchId == overBatch->getBatchId()) {
*insertBatchIndex = i + 1;
- if (!*targetBatch) break; // found insert position, quit
+ if (!*targetBatch) break; // found insert position, quit
}
if (overBatch->intersects(clippedBounds)) {
@@ -242,10 +240,10 @@ void LayerBuilder::onDeferOp(LinearAllocator& allocator, const BakedOpState* bak
// and issue them together in one draw.
flushLayerClears(allocator);
- if (CC_UNLIKELY(activeUnclippedSaveLayers.empty()
- && bakedState->computedState.opaqueOverClippedBounds
- && bakedState->computedState.clippedBounds.contains(repaintRect)
- && !Properties::debugOverdraw)) {
+ if (CC_UNLIKELY(activeUnclippedSaveLayers.empty() &&
+ bakedState->computedState.opaqueOverClippedBounds &&
+ bakedState->computedState.clippedBounds.contains(repaintRect) &&
+ !Properties::debugOverdraw)) {
// discard all deferred drawing ops, since new one will occlude them
clear();
}
@@ -258,7 +256,7 @@ void LayerBuilder::flushLayerClears(LinearAllocator& allocator) {
// put the verts in the frame allocator, since
// 1) SimpleRectsOps needs verts, not rects
// 2) even if mClearRects stored verts, std::vectors will move their contents
- Vertex* const verts = (Vertex*) allocator.create_trivial_array<Vertex>(vertCount);
+ Vertex* const verts = (Vertex*)allocator.create_trivial_array<Vertex>(vertCount);
Vertex* currentVert = verts;
Rect bounds = mClearRects[0];
@@ -269,35 +267,34 @@ void LayerBuilder::flushLayerClears(LinearAllocator& allocator) {
Vertex::set(currentVert++, rect.left, rect.bottom);
Vertex::set(currentVert++, rect.right, rect.bottom);
}
- mClearRects.clear(); // discard rects before drawing so this method isn't reentrant
+ mClearRects.clear(); // discard rects before drawing so this method isn't reentrant
// One or more unclipped saveLayers have been enqueued, with deferred clears.
// Flush all of these clears with a single draw
SkPaint* paint = allocator.create<SkPaint>();
paint->setBlendMode(SkBlendMode::kClear);
- SimpleRectsOp* op = allocator.create_trivial<SimpleRectsOp>(bounds,
- Matrix4::identity(), nullptr, paint,
- verts, vertCount);
- BakedOpState* bakedState = BakedOpState::directConstruct(allocator,
- &repaintClip, bounds, *op);
+ SimpleRectsOp* op = allocator.create_trivial<SimpleRectsOp>(
+ bounds, Matrix4::identity(), nullptr, paint, verts, vertCount);
+ BakedOpState* bakedState =
+ BakedOpState::directConstruct(allocator, &repaintClip, bounds, *op);
deferUnmergeableOp(allocator, bakedState, OpBatchType::Vertices);
}
}
-void LayerBuilder::deferUnmergeableOp(LinearAllocator& allocator,
- BakedOpState* op, batchid_t batchId) {
+void LayerBuilder::deferUnmergeableOp(LinearAllocator& allocator, BakedOpState* op,
+ batchid_t batchId) {
onDeferOp(allocator, op);
OpBatch* targetBatch = mBatchLookup[batchId];
size_t insertBatchIndex = mBatches.size();
if (targetBatch) {
- locateInsertIndex(batchId, op->computedState.clippedBounds,
- (BatchBase**)(&targetBatch), &insertBatchIndex);
+ locateInsertIndex(batchId, op->computedState.clippedBounds, (BatchBase**)(&targetBatch),
+ &insertBatchIndex);
}
if (targetBatch) {
targetBatch->batchOp(op);
- } else {
+ } else {
// new non-merging batch
targetBatch = allocator.create<OpBatch>(batchId, op);
mBatchLookup[batchId] = targetBatch;
@@ -305,8 +302,8 @@ void LayerBuilder::deferUnmergeableOp(LinearAllocator& allocator,
}
}
-void LayerBuilder::deferMergeableOp(LinearAllocator& allocator,
- BakedOpState* op, batchid_t batchId, mergeid_t mergeId) {
+void LayerBuilder::deferMergeableOp(LinearAllocator& allocator, BakedOpState* op, batchid_t batchId,
+ mergeid_t mergeId) {
onDeferOp(allocator, op);
MergingOpBatch* targetBatch = nullptr;
@@ -320,12 +317,12 @@ void LayerBuilder::deferMergeableOp(LinearAllocator& allocator,
}
size_t insertBatchIndex = mBatches.size();
- locateInsertIndex(batchId, op->computedState.clippedBounds,
- (BatchBase**)(&targetBatch), &insertBatchIndex);
+ locateInsertIndex(batchId, op->computedState.clippedBounds, (BatchBase**)(&targetBatch),
+ &insertBatchIndex);
if (targetBatch) {
targetBatch->mergeOp(op);
- } else {
+ } else {
// new merging batch
targetBatch = allocator.create<MergingOpBatch>(batchId, op);
mMergingBatchLookup[batchId].insert(std::make_pair(mergeId, targetBatch));
@@ -334,11 +331,11 @@ void LayerBuilder::deferMergeableOp(LinearAllocator& allocator,
}
}
-void LayerBuilder::replayBakedOpsImpl(void* arg,
- BakedOpReceiver* unmergedReceivers, MergedOpReceiver* mergedReceivers) const {
+void LayerBuilder::replayBakedOpsImpl(void* arg, BakedOpReceiver* unmergedReceivers,
+ MergedOpReceiver* mergedReceivers) const {
if (renderNode) {
- ATRACE_FORMAT_BEGIN("Issue HW Layer DisplayList %s %ux%u",
- renderNode->getName(), width, height);
+ ATRACE_FORMAT_BEGIN("Issue HW Layer DisplayList %s %ux%u", renderNode->getName(), width,
+ height);
} else {
ATRACE_BEGIN("flush drawing commands");
}
@@ -348,12 +345,9 @@ void LayerBuilder::replayBakedOpsImpl(void* arg,
if (size > 1 && batch->isMerging()) {
int opId = batch->getOps()[0]->op->opId;
const MergingOpBatch* mergingBatch = static_cast<const MergingOpBatch*>(batch);
- MergedBakedOpList data = {
- batch->getOps().data(),
- size,
- mergingBatch->getClipSideFlags(),
- mergingBatch->getClipRect()
- };
+ MergedBakedOpList data = {batch->getOps().data(), size,
+ mergingBatch->getClipSideFlags(),
+ mergingBatch->getClipRect()};
mergedReceivers[opId](arg, data);
} else {
for (const BakedOpState* op : batch->getOps()) {
@@ -373,13 +367,12 @@ void LayerBuilder::clear() {
}
void LayerBuilder::dump() const {
- ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p (%s)",
- this, width, height, offscreenBuffer, beginLayerOp,
- renderNode, renderNode ? renderNode->getName() : "-");
+ ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p (%s)", this, width, height,
+ offscreenBuffer, beginLayerOp, renderNode, renderNode ? renderNode->getName() : "-");
for (const BatchBase* batch : mBatches) {
batch->dump();
}
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/LayerBuilder.h b/libs/hwui/LayerBuilder.h
index 4de432c5e7be..c799d48f7821 100644
--- a/libs/hwui/LayerBuilder.h
+++ b/libs/hwui/LayerBuilder.h
@@ -20,8 +20,8 @@
#include "Rect.h"
#include "utils/Macros.h"
-#include <vector>
#include <unordered_map>
+#include <vector>
struct SkRect;
@@ -42,22 +42,22 @@ typedef int batchid_t;
typedef const void* mergeid_t;
namespace OpBatchType {
- enum {
- Bitmap,
- MergedPatch,
- AlphaVertices,
- Vertices,
- AlphaMaskTexture,
- Text,
- ColorText,
- Shadow,
- TextureLayer,
- Functor,
- CopyToLayer,
- CopyFromLayer,
-
- Count // must be last
- };
+enum {
+ Bitmap,
+ MergedPatch,
+ AlphaVertices,
+ Vertices,
+ AlphaMaskTexture,
+ Text,
+ ColorText,
+ Shadow,
+ TextureLayer,
+ Functor,
+ CopyToLayer,
+ CopyFromLayer,
+
+ Count // must be last
+};
}
typedef void (*BakedOpReceiver)(void*, const BakedOpState&);
@@ -68,37 +68,36 @@ typedef void (*MergedOpReceiver)(void*, const MergedBakedOpList& opList);
* for a single FBO/layer.
*/
class LayerBuilder {
-// Prevent copy/assign because users may stash pointer to offscreenBuffer and viewportClip
-PREVENT_COPY_AND_ASSIGN(LayerBuilder);
+ // Prevent copy/assign because users may stash pointer to offscreenBuffer and viewportClip
+ PREVENT_COPY_AND_ASSIGN(LayerBuilder);
+
public:
// Create LayerBuilder for Fbo0
LayerBuilder(uint32_t width, uint32_t height, const Rect& repaintRect)
- : LayerBuilder(width, height, repaintRect, nullptr, nullptr) {};
+ : LayerBuilder(width, height, repaintRect, nullptr, nullptr){};
// Create LayerBuilder for an offscreen layer, where beginLayerOp is present for a
// saveLayer, renderNode is present for a HW layer.
- LayerBuilder(uint32_t width, uint32_t height,
- const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
+ LayerBuilder(uint32_t width, uint32_t height, const Rect& repaintRect,
+ const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
// iterate back toward target to see if anything drawn since should overlap the new op
// if no target, merging ops still iterate to find similar batch to insert after
- void locateInsertIndex(int batchId, const Rect& clippedBounds,
- BatchBase** targetBatch, size_t* insertBatchIndex) const;
+ void locateInsertIndex(int batchId, const Rect& clippedBounds, BatchBase** targetBatch,
+ size_t* insertBatchIndex) const;
void deferUnmergeableOp(LinearAllocator& allocator, BakedOpState* op, batchid_t batchId);
// insertion point of a new batch, will hopefully be immediately after similar batch
// (generally, should be similar shader)
- void deferMergeableOp(LinearAllocator& allocator,
- BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
+ void deferMergeableOp(LinearAllocator& allocator, BakedOpState* op, batchid_t batchId,
+ mergeid_t mergeId);
void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers, MergedOpReceiver*) const;
void deferLayerClear(const Rect& dstRect);
- bool empty() const {
- return mBatches.empty();
- }
+ bool empty() const { return mBatches.empty(); }
void clear();
@@ -114,6 +113,7 @@ public:
// list of deferred CopyFromLayer ops, to be deferred upon encountering EndUnclippedLayerOps
std::vector<BakedOpState*> activeUnclippedSaveLayers;
+
private:
void onDeferOp(LinearAllocator& allocator, const BakedOpState* bakedState);
void flushLayerClears(LinearAllocator& allocator);
@@ -128,10 +128,10 @@ private:
std::unordered_map<mergeid_t, MergingOpBatch*> mMergingBatchLookup[OpBatchType::Count];
// Maps batch ids to the most recent *non-merging* batch of that id
- OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };
+ OpBatch* mBatchLookup[OpBatchType::Count] = {nullptr};
std::vector<Rect> mClearRects;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/LayerUpdateQueue.cpp b/libs/hwui/LayerUpdateQueue.cpp
index 95f5cfb33474..fd5c66101cd3 100644
--- a/libs/hwui/LayerUpdateQueue.cpp
+++ b/libs/hwui/LayerUpdateQueue.cpp
@@ -39,5 +39,5 @@ void LayerUpdateQueue::enqueueLayerWithDamage(RenderNode* renderNode, Rect damag
}
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/LayerUpdateQueue.h b/libs/hwui/LayerUpdateQueue.h
index 38f3596d70df..b14b80cc598a 100644
--- a/libs/hwui/LayerUpdateQueue.h
+++ b/libs/hwui/LayerUpdateQueue.h
@@ -17,12 +17,12 @@
#ifndef ANDROID_HWUI_LAYER_UPDATE_QUEUE_H
#define ANDROID_HWUI_LAYER_UPDATE_QUEUE_H
+#include <utils/StrongPointer.h>
#include "Rect.h"
#include "utils/Macros.h"
-#include <utils/StrongPointer.h>
-#include <vector>
#include <unordered_map>
+#include <vector>
namespace android {
namespace uirenderer {
@@ -31,11 +31,11 @@ class RenderNode;
class LayerUpdateQueue {
PREVENT_COPY_AND_ASSIGN(LayerUpdateQueue);
+
public:
struct Entry {
Entry(RenderNode* renderNode, const Rect& damage)
- : renderNode(renderNode)
- , damage(damage) {}
+ : renderNode(renderNode), damage(damage) {}
sp<RenderNode> renderNode;
Rect damage;
};
@@ -44,11 +44,12 @@ public:
void enqueueLayerWithDamage(RenderNode* renderNode, Rect dirty);
void clear();
const std::vector<Entry>& entries() const { return mEntries; }
+
private:
std::vector<Entry> mEntries;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_LAYER_UPDATE_QUEUE_H
+#endif // ANDROID_HWUI_LAYER_UPDATE_QUEUE_H
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index a936661f86f9..d84ed321a4cb 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -43,24 +43,24 @@ const Matrix4& Matrix4::identity() {
}
void Matrix4::loadIdentity() {
- data[kScaleX] = 1.0f;
- data[kSkewY] = 0.0f;
- data[2] = 0.0f;
+ data[kScaleX] = 1.0f;
+ data[kSkewY] = 0.0f;
+ data[2] = 0.0f;
data[kPerspective0] = 0.0f;
- data[kSkewX] = 0.0f;
- data[kScaleY] = 1.0f;
- data[6] = 0.0f;
+ data[kSkewX] = 0.0f;
+ data[kScaleY] = 1.0f;
+ data[6] = 0.0f;
data[kPerspective1] = 0.0f;
- data[8] = 0.0f;
- data[9] = 0.0f;
- data[kScaleZ] = 1.0f;
- data[11] = 0.0f;
+ data[8] = 0.0f;
+ data[9] = 0.0f;
+ data[kScaleZ] = 1.0f;
+ data[11] = 0.0f;
- data[kTranslateX] = 0.0f;
- data[kTranslateY] = 0.0f;
- data[kTranslateZ] = 0.0f;
+ data[kTranslateX] = 0.0f;
+ data[kTranslateY] = 0.0f;
+ data[kTranslateZ] = 0.0f;
data[kPerspective2] = 1.0f;
mType = kTypeIdentity | kTypeRectToRect;
@@ -75,7 +75,7 @@ uint8_t Matrix4::getType() const {
mType = kTypeIdentity;
if (data[kPerspective0] != 0.0f || data[kPerspective1] != 0.0f ||
- data[kPerspective2] != 1.0f) {
+ data[kPerspective2] != 1.0f) {
mType |= kTypePerspective;
}
@@ -105,7 +105,7 @@ uint8_t Matrix4::getType() const {
// it doesn't preserve rectangles.
if (!(mType & kTypePerspective)) {
if ((isZero(m00) && isZero(m11) && !isZero(m01) && !isZero(m10)) ||
- (isZero(m01) && isZero(m10) && !isZero(m00) && !isZero(m11))) {
+ (isZero(m01) && isZero(m10) && !isZero(m00) && !isZero(m11))) {
mType |= kTypeRectToRect;
}
}
@@ -155,17 +155,17 @@ void Matrix4::load(const float* v) {
void Matrix4::load(const SkMatrix& v) {
memset(data, 0, sizeof(data));
- data[kScaleX] = v[SkMatrix::kMScaleX];
- data[kSkewX] = v[SkMatrix::kMSkewX];
+ data[kScaleX] = v[SkMatrix::kMScaleX];
+ data[kSkewX] = v[SkMatrix::kMSkewX];
data[kTranslateX] = v[SkMatrix::kMTransX];
- data[kSkewY] = v[SkMatrix::kMSkewY];
- data[kScaleY] = v[SkMatrix::kMScaleY];
+ data[kSkewY] = v[SkMatrix::kMSkewY];
+ data[kScaleY] = v[SkMatrix::kMScaleY];
data[kTranslateY] = v[SkMatrix::kMTransY];
- data[kPerspective0] = v[SkMatrix::kMPersp0];
- data[kPerspective1] = v[SkMatrix::kMPersp1];
- data[kPerspective2] = v[SkMatrix::kMPersp2];
+ data[kPerspective0] = v[SkMatrix::kMPersp0];
+ data[kPerspective1] = v[SkMatrix::kMPersp1];
+ data[kPerspective2] = v[SkMatrix::kMPersp2];
data[kScaleZ] = 1.0f;
@@ -183,10 +183,10 @@ void Matrix4::copyTo(SkMatrix& v) const {
v.reset();
v.set(SkMatrix::kMScaleX, data[kScaleX]);
- v.set(SkMatrix::kMSkewX, data[kSkewX]);
+ v.set(SkMatrix::kMSkewX, data[kSkewX]);
v.set(SkMatrix::kMTransX, data[kTranslateX]);
- v.set(SkMatrix::kMSkewY, data[kSkewY]);
+ v.set(SkMatrix::kMSkewY, data[kSkewY]);
v.set(SkMatrix::kMScaleY, data[kScaleY]);
v.set(SkMatrix::kMTransY, data[kTranslateY]);
@@ -201,13 +201,13 @@ void Matrix4::loadInverse(const Matrix4& v) {
// Reset the matrix
// Unnamed fields are never written to except by
// loadIdentity(), they don't need to be reset
- data[kScaleX] = 1.0f;
- data[kSkewX] = 0.0f;
+ data[kScaleX] = 1.0f;
+ data[kSkewX] = 0.0f;
- data[kScaleY] = 1.0f;
- data[kSkewY] = 0.0f;
+ data[kScaleY] = 1.0f;
+ data[kSkewY] = 0.0f;
- data[kScaleZ] = 1.0f;
+ data[kScaleZ] = 1.0f;
data[kPerspective0] = 0.0f;
data[kPerspective1] = 0.0f;
@@ -215,43 +215,48 @@ void Matrix4::loadInverse(const Matrix4& v) {
// No need to deal with kTranslateZ because isPureTranslate()
// only returns true when the kTranslateZ component is 0
- data[kTranslateX] = -v.data[kTranslateX];
- data[kTranslateY] = -v.data[kTranslateY];
- data[kTranslateZ] = 0.0f;
+ data[kTranslateX] = -v.data[kTranslateX];
+ data[kTranslateY] = -v.data[kTranslateY];
+ data[kTranslateZ] = 0.0f;
// A "pure translate" matrix can be identity or translation
mType = v.getType();
return;
}
- double scale = 1.0 /
- (v.data[kScaleX] * ((double) v.data[kScaleY] * v.data[kPerspective2] -
- (double) v.data[kTranslateY] * v.data[kPerspective1]) +
- v.data[kSkewX] * ((double) v.data[kTranslateY] * v.data[kPerspective0] -
- (double) v.data[kSkewY] * v.data[kPerspective2]) +
- v.data[kTranslateX] * ((double) v.data[kSkewY] * v.data[kPerspective1] -
- (double) v.data[kScaleY] * v.data[kPerspective0]));
+ double scale = 1.0 / (v.data[kScaleX] * ((double)v.data[kScaleY] * v.data[kPerspective2] -
+ (double)v.data[kTranslateY] * v.data[kPerspective1]) +
+ v.data[kSkewX] * ((double)v.data[kTranslateY] * v.data[kPerspective0] -
+ (double)v.data[kSkewY] * v.data[kPerspective2]) +
+ v.data[kTranslateX] * ((double)v.data[kSkewY] * v.data[kPerspective1] -
+ (double)v.data[kScaleY] * v.data[kPerspective0]));
data[kScaleX] = (v.data[kScaleY] * v.data[kPerspective2] -
- v.data[kTranslateY] * v.data[kPerspective1]) * scale;
- data[kSkewX] = (v.data[kTranslateX] * v.data[kPerspective1] -
- v.data[kSkewX] * v.data[kPerspective2]) * scale;
- data[kTranslateX] = (v.data[kSkewX] * v.data[kTranslateY] -
- v.data[kTranslateX] * v.data[kScaleY]) * scale;
-
- data[kSkewY] = (v.data[kTranslateY] * v.data[kPerspective0] -
- v.data[kSkewY] * v.data[kPerspective2]) * scale;
+ v.data[kTranslateY] * v.data[kPerspective1]) *
+ scale;
+ data[kSkewX] =
+ (v.data[kTranslateX] * v.data[kPerspective1] - v.data[kSkewX] * v.data[kPerspective2]) *
+ scale;
+ data[kTranslateX] =
+ (v.data[kSkewX] * v.data[kTranslateY] - v.data[kTranslateX] * v.data[kScaleY]) * scale;
+
+ data[kSkewY] =
+ (v.data[kTranslateY] * v.data[kPerspective0] - v.data[kSkewY] * v.data[kPerspective2]) *
+ scale;
data[kScaleY] = (v.data[kScaleX] * v.data[kPerspective2] -
- v.data[kTranslateX] * v.data[kPerspective0]) * scale;
- data[kTranslateY] = (v.data[kTranslateX] * v.data[kSkewY] -
- v.data[kScaleX] * v.data[kTranslateY]) * scale;
-
- data[kPerspective0] = (v.data[kSkewY] * v.data[kPerspective1] -
- v.data[kScaleY] * v.data[kPerspective0]) * scale;
- data[kPerspective1] = (v.data[kSkewX] * v.data[kPerspective0] -
- v.data[kScaleX] * v.data[kPerspective1]) * scale;
- data[kPerspective2] = (v.data[kScaleX] * v.data[kScaleY] -
- v.data[kSkewX] * v.data[kSkewY]) * scale;
+ v.data[kTranslateX] * v.data[kPerspective0]) *
+ scale;
+ data[kTranslateY] =
+ (v.data[kTranslateX] * v.data[kSkewY] - v.data[kScaleX] * v.data[kTranslateY]) * scale;
+
+ data[kPerspective0] =
+ (v.data[kSkewY] * v.data[kPerspective1] - v.data[kScaleY] * v.data[kPerspective0]) *
+ scale;
+ data[kPerspective1] =
+ (v.data[kSkewX] * v.data[kPerspective0] - v.data[kScaleX] * v.data[kPerspective1]) *
+ scale;
+ data[kPerspective2] =
+ (v.data[kScaleX] * v.data[kScaleY] - v.data[kSkewX] * v.data[kSkewY]) * scale;
mType = kTypeUnknown;
}
@@ -298,13 +303,13 @@ void Matrix4::loadScale(float sx, float sy, float sz) {
void Matrix4::loadSkew(float sx, float sy) {
loadIdentity();
- data[kScaleX] = 1.0f;
- data[kSkewX] = sx;
- data[kTranslateX] = 0.0f;
+ data[kScaleX] = 1.0f;
+ data[kSkewX] = sx;
+ data[kTranslateX] = 0.0f;
- data[kSkewY] = sy;
- data[kScaleY] = 1.0f;
- data[kTranslateY] = 0.0f;
+ data[kSkewY] = sy;
+ data[kScaleY] = 1.0f;
+ data[kTranslateY] = 0.0f;
data[kPerspective0] = 0.0f;
data[kPerspective1] = 0.0f;
@@ -320,23 +325,23 @@ void Matrix4::loadRotate(float angle) {
loadIdentity();
- data[kScaleX] = c;
- data[kSkewX] = -s;
+ data[kScaleX] = c;
+ data[kSkewX] = -s;
- data[kSkewY] = s;
- data[kScaleY] = c;
+ data[kSkewY] = s;
+ data[kScaleY] = c;
mType = kTypeUnknown;
}
void Matrix4::loadRotate(float angle, float x, float y, float z) {
- data[kPerspective0] = 0.0f;
- data[kPerspective1] = 0.0f;
- data[11] = 0.0f;
- data[kTranslateX] = 0.0f;
- data[kTranslateY] = 0.0f;
- data[kTranslateZ] = 0.0f;
- data[kPerspective2] = 1.0f;
+ data[kPerspective0] = 0.0f;
+ data[kPerspective1] = 0.0f;
+ data[11] = 0.0f;
+ data[kTranslateX] = 0.0f;
+ data[kTranslateY] = 0.0f;
+ data[kTranslateZ] = 0.0f;
+ data[kPerspective2] = 1.0f;
angle *= float(M_PI / 180.0f);
float c = cosf(angle);
@@ -356,27 +361,27 @@ void Matrix4::loadRotate(float angle, float x, float y, float z) {
const float ys = y * s;
const float zs = z * s;
- data[kScaleX] = x * x * nc + c;
- data[kSkewX] = xy * nc - zs;
- data[8] = zx * nc + ys;
- data[kSkewY] = xy * nc + zs;
- data[kScaleY] = y * y * nc + c;
- data[9] = yz * nc - xs;
- data[2] = zx * nc - ys;
- data[6] = yz * nc + xs;
- data[kScaleZ] = z * z * nc + c;
+ data[kScaleX] = x * x * nc + c;
+ data[kSkewX] = xy * nc - zs;
+ data[8] = zx * nc + ys;
+ data[kSkewY] = xy * nc + zs;
+ data[kScaleY] = y * y * nc + c;
+ data[9] = yz * nc - xs;
+ data[2] = zx * nc - ys;
+ data[6] = yz * nc + xs;
+ data[kScaleZ] = z * z * nc + c;
mType = kTypeUnknown;
}
void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
- for (int i = 0 ; i < 4 ; i++) {
+ for (int i = 0; i < 4; i++) {
float x = 0;
float y = 0;
float z = 0;
float w = 0;
- for (int j = 0 ; j < 4 ; j++) {
+ for (int j = 0; j < 4; j++) {
const float e = v.get(i, j);
x += u.get(j, 0) * e;
y += u.get(j, 1) * e;
@@ -412,7 +417,7 @@ float Matrix4::mapZ(const Vector3& orig) const {
}
void Matrix4::mapPoint3d(Vector3& vec) const {
- //TODO: optimize simple case
+ // TODO: optimize simple case
const Vector3 orig(vec);
vec.x = orig.x * data[kScaleX] + orig.y * data[kSkewX] + orig.z * data[8] + data[kTranslateX];
vec.y = orig.x * data[kSkewY] + orig.y * data[kScaleY] + orig.z * data[9] + data[kTranslateY];
@@ -469,16 +474,11 @@ void Matrix4::mapRect(Rect& r) const {
return;
}
- float vertices[] = {
- r.left, r.top,
- r.right, r.top,
- r.right, r.bottom,
- r.left, r.bottom
- };
+ float vertices[] = {r.left, r.top, r.right, r.top, r.right, r.bottom, r.left, r.bottom};
float x, y, z;
- for (int i = 0; i < 8; i+= 2) {
+ for (int i = 0; i < 8; i += 2) {
float px = vertices[i];
float py = vertices[i + 1];
@@ -498,10 +498,14 @@ void Matrix4::mapRect(Rect& r) const {
x = vertices[i];
y = vertices[i + 1];
- if (x < r.left) r.left = x;
- else if (x > r.right) r.right = x;
- if (y < r.top) r.top = y;
- else if (y > r.bottom) r.bottom = y;
+ if (x < r.left)
+ r.left = x;
+ else if (x > r.right)
+ r.right = x;
+ if (y < r.top)
+ r.top = y;
+ else if (y > r.bottom)
+ r.bottom = y;
}
}
@@ -522,5 +526,5 @@ void Matrix4::dump(const char* label) const {
ALOGD("]");
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index ba9cbbe02ec1..f0a3a959617d 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -18,27 +18,26 @@
#include "Rect.h"
+#include <SkMatrix.h>
#include <cutils/compiler.h>
#include <iomanip>
#include <ostream>
-#include <SkMatrix.h>
namespace android {
namespace uirenderer {
#define SK_MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]"
-#define SK_MATRIX_ARGS(m) \
- (m)->get(0), (m)->get(1), (m)->get(2), \
- (m)->get(3), (m)->get(4), (m)->get(5), \
- (m)->get(6), (m)->get(7), (m)->get(8)
+#define SK_MATRIX_ARGS(m) \
+ (m)->get(0), (m)->get(1), (m)->get(2), (m)->get(3), (m)->get(4), (m)->get(5), (m)->get(6), \
+ (m)->get(7), (m)->get(8)
-#define MATRIX_4_STRING "[%.2f %.2f %.2f %.2f] [%.2f %.2f %.2f %.2f]" \
+#define MATRIX_4_STRING \
+ "[%.2f %.2f %.2f %.2f] [%.2f %.2f %.2f %.2f]" \
" [%.2f %.2f %.2f %.2f] [%.2f %.2f %.2f %.2f]"
-#define MATRIX_4_ARGS(m) \
- (m)->data[0], (m)->data[4], (m)->data[8], (m)->data[12], \
- (m)->data[1], (m)->data[5], (m)->data[9], (m)->data[13], \
- (m)->data[2], (m)->data[6], (m)->data[10], (m)->data[14], \
- (m)->data[3], (m)->data[7], (m)->data[11], (m)->data[15] \
+#define MATRIX_4_ARGS(m) \
+ (m)->data[0], (m)->data[4], (m)->data[8], (m)->data[12], (m)->data[1], (m)->data[5], \
+ (m)->data[9], (m)->data[13], (m)->data[2], (m)->data[6], (m)->data[10], (m)->data[14], \
+ (m)->data[3], (m)->data[7], (m)->data[11], (m)->data[15]
///////////////////////////////////////////////////////////////////////////////
// Classes
@@ -77,21 +76,15 @@ public:
static const int sGeometryMask = 0xf;
- Matrix4() {
- loadIdentity();
- }
+ Matrix4() { loadIdentity(); }
- explicit Matrix4(const float* v) {
- load(v);
- }
+ explicit Matrix4(const float* v) { load(v); }
Matrix4(const SkMatrix& v) { // NOLINT, implicit
load(v);
}
- float operator[](int index) const {
- return data[index];
- }
+ float operator[](int index) const { return data[index]; }
float& operator[](int index) {
mType = kTypeUnknown;
@@ -107,9 +100,7 @@ public:
return !memcmp(&a.data[0], &b.data[0], 16 * sizeof(float));
}
- friend bool operator!=(const Matrix4& a, const Matrix4& b) {
- return !(a == b);
- }
+ friend bool operator!=(const Matrix4& a, const Matrix4& b) { return !(a == b); }
void loadIdentity();
@@ -126,9 +117,7 @@ public:
void loadMultiply(const Matrix4& u, const Matrix4& v);
void loadOrtho(float left, float right, float bottom, float top, float near, float far);
- void loadOrtho(int width, int height) {
- loadOrtho(0, width, height, 0, -1, 1);
- }
+ void loadOrtho(int width, int height) { loadOrtho(0, width, height, 0, -1, 1); }
uint8_t getType() const;
@@ -208,8 +197,8 @@ public:
float mapZ(const Vector3& orig) const;
void mapPoint3d(Vector3& vec) const;
- void mapPoint(float& x, float& y) const; // 2d only
- void mapRect(Rect& r) const; // 2d only
+ void mapPoint(float& x, float& y) const; // 2d only
+ void mapRect(Rect& r) const; // 2d only
float getTranslateX() const;
float getTranslateY() const;
@@ -241,17 +230,13 @@ public:
private:
mutable uint8_t mType;
- inline float get(int i, int j) const {
- return data[i * 4 + j];
- }
+ inline float get(int i, int j) const { return data[i * 4 + j]; }
- inline void set(int i, int j, float v) {
- data[i * 4 + j] = v;
- }
+ inline void set(int i, int j, float v) { data[i * 4 + j] = v; }
uint8_t getGeometryType() const;
-}; // class Matrix4
+}; // class Matrix4
///////////////////////////////////////////////////////////////////////////////
// Types
@@ -259,6 +244,5 @@ private:
typedef Matrix4 mat4;
-}; // namespace uirenderer
-}; // namespace android
-
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/NinePatchUtils.h b/libs/hwui/NinePatchUtils.h
index e989a4680a60..db9509fff378 100644
--- a/libs/hwui/NinePatchUtils.h
+++ b/libs/hwui/NinePatchUtils.h
@@ -20,7 +20,7 @@ namespace android {
namespace NinePatchUtils {
static inline void SetLatticeDivs(SkCanvas::Lattice* lattice, const Res_png_9patch& chunk,
- int width, int height) {
+ int width, int height) {
lattice->fXCount = chunk.numXDivs;
lattice->fYCount = chunk.numYDivs;
lattice->fXDivs = chunk.getXDivs();
@@ -53,10 +53,13 @@ static inline int NumDistinctRects(const SkCanvas::Lattice& lattice) {
return xRects * yRects;
}
-static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice::Flags* flags,
- int numFlags, const Res_png_9patch& chunk) {
- lattice->fFlags = flags;
- sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::Flags));
+static inline void SetLatticeFlags(SkCanvas::Lattice* lattice,
+ SkCanvas::Lattice::RectType* flags, int numFlags, const Res_png_9patch& chunk,
+ SkColor* colors) {
+ lattice->fRectTypes = flags;
+ lattice->fColors = colors;
+ sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::RectType));
+ sk_bzero(colors, numFlags * sizeof(SkColor));
bool needPadRow = lattice->fYCount > 0 && 0 == lattice->fYDivs[0];
bool needPadCol = lattice->fXCount > 0 && 0 == lattice->fXDivs[0];
@@ -65,6 +68,7 @@ static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice
if (needPadRow) {
// Skip flags for the degenerate first row of rects.
flags += lattice->fXCount + 1;
+ colors += lattice->fXCount + 1;
yCount--;
}
@@ -75,22 +79,30 @@ static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice
if (0 == x && needPadCol) {
// First rect of each column is degenerate, skip the flag.
flags++;
+ colors++;
continue;
}
- if (0 == chunk.getColors()[i++]) {
- *flags = SkCanvas::Lattice::kTransparent_Flags;
+ uint32_t currentColor = chunk.getColors()[i++];
+ if (Res_png_9patch::TRANSPARENT_COLOR == currentColor) {
+ *flags = SkCanvas::Lattice::kTransparent;
+ setFlags = true;
+ } else if (Res_png_9patch::NO_COLOR != currentColor) {
+ *flags = SkCanvas::Lattice::kFixedColor;
+ *colors = currentColor;
setFlags = true;
}
flags++;
+ colors++;
}
}
if (!setFlags) {
- lattice->fFlags = nullptr;
+ lattice->fRectTypes = nullptr;
+ lattice->fColors = nullptr;
}
}
-}; // namespace NinePatchUtils
-}; // namespace android
+}; // namespace NinePatchUtils
+}; // namespace android
diff --git a/libs/hwui/OpDumper.cpp b/libs/hwui/OpDumper.cpp
index f4b7ee0fe430..5d2ccc77e82f 100644
--- a/libs/hwui/OpDumper.cpp
+++ b/libs/hwui/OpDumper.cpp
@@ -34,14 +34,13 @@ void OpDumper::dump(const RecordedOp& op, std::ostream& output, int level) {
op.localMatrix.mapRect(localBounds);
output << sOpNameLut[op.opId] << " " << localBounds;
- if (op.localClip
- && (!op.localClip->rect.contains(localBounds) || op.localClip->intersectWithRoot)) {
- output << std::fixed << std::setprecision(0)
- << " clip=" << op.localClip->rect
- << " mode=" << (int)op.localClip->mode;
+ if (op.localClip &&
+ (!op.localClip->rect.contains(localBounds) || op.localClip->intersectWithRoot)) {
+ output << std::fixed << std::setprecision(0) << " clip=" << op.localClip->rect
+ << " mode=" << (int)op.localClip->mode;
if (op.localClip->intersectWithRoot) {
- output << " iwr";
+ output << " iwr";
}
}
}
@@ -50,5 +49,5 @@ const char* OpDumper::opName(const RecordedOp& op) {
return sOpNameLut[op.opId];
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/OpDumper.h b/libs/hwui/OpDumper.h
index a82289c7cca2..edbe381fcc72 100644
--- a/libs/hwui/OpDumper.h
+++ b/libs/hwui/OpDumper.h
@@ -29,5 +29,5 @@ public:
static const char* opName(const RecordedOp& op);
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index 751e2037db91..11432d629650 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -17,30 +17,29 @@
#include "OpenGLReadback.h"
#include "Caches.h"
-#include "Image.h"
-#include "GlopBuilder.h"
#include "GlLayer.h"
+#include "GlopBuilder.h"
+#include "Image.h"
#include "renderstate/RenderState.h"
#include "renderthread/EglManager.h"
#include "utils/GLUtils.h"
#include <GLES2/gl2.h>
+#include <gui/Surface.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
-#include <gui/Surface.h>
namespace android {
namespace uirenderer {
CopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect,
- SkBitmap* bitmap) {
+ SkBitmap* bitmap) {
ATRACE_CALL();
// Setup the source
sp<GraphicBuffer> sourceBuffer;
sp<Fence> sourceFence;
Matrix4 texTransform;
- status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence,
- texTransform.data);
+ status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data);
texTransform.invalidateType();
if (err != NO_ERROR) {
ALOGW("Failed to get last queued buffer, error = %d", err);
@@ -64,7 +63,8 @@ CopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect
}
CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
- Matrix4& texTransform, const Rect& srcRect, SkBitmap* bitmap) {
+ Matrix4& texTransform, const Rect& srcRect,
+ SkBitmap* bitmap) {
mRenderThread.eglManager().initialize();
// TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via
// GL_OES_EGL_image, which doesn't work since we need samplerExternalOES
@@ -72,11 +72,11 @@ CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
// Create the EGLImage object that maps the GraphicBuffer
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- EGLClientBuffer clientBuffer = (EGLClientBuffer) graphicBuffer->getNativeBuffer();
- EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
+ EGLClientBuffer clientBuffer = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
+ EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
- EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
+ EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ clientBuffer, attrs);
if (sourceImage == EGL_NO_IMAGE_KHR) {
ALOGW("eglCreateImageKHR failed (%#x)", eglGetError());
@@ -85,8 +85,8 @@ CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
uint32_t width = graphicBuffer->getWidth();
uint32_t height = graphicBuffer->getHeight();
- CopyResult copyResult = copyImageInto(sourceImage, texTransform, width, height,
- srcRect, bitmap);
+ CopyResult copyResult =
+ copyImageInto(sourceImage, texTransform, width, height, srcRect, bitmap);
// All we're flushing & finishing is the deletion of the texture since
// copyImageInto already did a major flush & finish as an implicit
@@ -105,10 +105,7 @@ CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, S
}
static float sFlipVInit[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
+ 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,
};
static const Matrix4 sFlipV(sFlipVInit);
@@ -116,20 +113,19 @@ static const Matrix4 sFlipV(sFlipVInit);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
- Texture& sourceTexture, const Matrix4& texTransform, const Rect& srcRect,
- SkBitmap* bitmap) {
+inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState, Texture& sourceTexture,
+ const Matrix4& texTransform, const Rect& srcRect,
+ SkBitmap* bitmap) {
int destWidth = bitmap->width();
int destHeight = bitmap->height();
- if (destWidth > caches.maxTextureSize
- || destHeight > caches.maxTextureSize) {
- ALOGW("Can't copy surface into bitmap, %dx%d exceeds max texture size %d",
- destWidth, destHeight, caches.maxTextureSize);
+ if (destWidth > caches.maxTextureSize || destHeight > caches.maxTextureSize) {
+ ALOGW("Can't copy surface into bitmap, %dx%d exceeds max texture size %d", destWidth,
+ destHeight, caches.maxTextureSize);
return CopyResult::DestinationInvalid;
}
if (bitmap->colorType() == kRGBA_F16_SkColorType &&
- !caches.extensions().hasRenderableFloatTextures()) {
+ !caches.extensions().hasRenderableFloatTextures()) {
ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
return CopyResult::DestinationInvalid;
}
@@ -189,10 +185,8 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, destWidth, destHeight,
- 0, format, type, nullptr);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, texture, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, destWidth, destHeight, 0, format, type, nullptr);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
{
bool requiresFilter;
@@ -209,15 +203,15 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
// GLES coordinates.
croppedTexTransform.multiply(sFlipV);
croppedTexTransform.translate(srcRect.left / sourceTexture.width(),
- srcRect.top / sourceTexture.height(), 0);
+ srcRect.top / sourceTexture.height(), 0);
croppedTexTransform.scale(srcRect.getWidth() / sourceTexture.width(),
- srcRect.getHeight() / sourceTexture.height(), 1);
+ srcRect.getHeight() / sourceTexture.height(), 1);
croppedTexTransform.multiply(sFlipV);
- requiresFilter = srcRect.getWidth() != (float) destWidth
- || srcRect.getHeight() != (float) destHeight;
+ requiresFilter = srcRect.getWidth() != (float)destWidth ||
+ srcRect.getHeight() != (float)destHeight;
} else {
- requiresFilter = sourceTexture.width() != (uint32_t) destWidth
- || sourceTexture.height() != (uint32_t) destHeight;
+ requiresFilter = sourceTexture.width() != (uint32_t)destWidth ||
+ sourceTexture.height() != (uint32_t)destHeight;
}
Glop glop;
GlopBuilder(renderState, caches, &glop)
@@ -232,8 +226,7 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
renderState.render(glop, ortho, false);
// TODO: We should convert to linear space when the target is RGBA16F
- glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
- type, bitmap->getPixels());
+ glReadPixels(0, 0, bitmap->width(), bitmap->height(), format, type, bitmap->getPixels());
bitmap->notifyPixelsChanged();
}
@@ -246,10 +239,9 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
return CopyResult::Success;
}
-CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage,
- const Matrix4& imgTransform, int imgWidth, int imgHeight, const Rect& srcRect,
- SkBitmap* bitmap) {
-
+CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
+ int imgWidth, int imgHeight, const Rect& srcRect,
+ SkBitmap* bitmap) {
// If this is a 90 or 270 degree rotation we need to swap width/height
// This is a fuzzy way of checking that.
if (imgTransform[Matrix4::kSkewX] >= 0.5f || imgTransform[Matrix4::kSkewX] <= -0.5f) {
@@ -271,26 +263,25 @@ CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage,
Texture sourceTexture(caches);
sourceTexture.wrap(sourceTexId, imgWidth, imgHeight, 0, 0 /* total lie */,
- GL_TEXTURE_EXTERNAL_OES);
+ GL_TEXTURE_EXTERNAL_OES);
- CopyResult copyResult = copyTextureInto(caches, mRenderThread.renderState(),
- sourceTexture, imgTransform, srcRect, bitmap);
+ CopyResult copyResult = copyTextureInto(caches, mRenderThread.renderState(), sourceTexture,
+ imgTransform, srcRect, bitmap);
sourceTexture.deleteTexture();
return copyResult;
}
-bool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread,
- GlLayer& layer, SkBitmap* bitmap) {
+bool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer,
+ SkBitmap* bitmap) {
if (!layer.isRenderable()) {
// layer has never been updated by DeferredLayerUpdater, abort copy
return false;
}
- return CopyResult::Success == copyTextureInto(Caches::getInstance(),
- renderThread.renderState(), layer.getTexture(), layer.getTexTransform(),
- Rect(), bitmap);
+ return CopyResult::Success == copyTextureInto(Caches::getInstance(), renderThread.renderState(),
+ layer.getTexture(), layer.getTexTransform(),
+ Rect(), bitmap);
}
-
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/OpenGLReadback.h b/libs/hwui/OpenGLReadback.h
index 403f2e34d515..ca40738b4901 100644
--- a/libs/hwui/OpenGLReadback.h
+++ b/libs/hwui/OpenGLReadback.h
@@ -30,19 +30,21 @@ class GlLayer;
class OpenGLReadback : public Readback {
public:
virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
- SkBitmap* bitmap) override;
+ SkBitmap* bitmap) override;
virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
- SkBitmap* bitmap) override;
+ SkBitmap* bitmap) override;
protected:
explicit OpenGLReadback(renderthread::RenderThread& thread) : Readback(thread) {}
virtual ~OpenGLReadback() {}
virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
- int imgWidth, int imgHeight, const Rect& srcRect, SkBitmap* bitmap) = 0;
+ int imgWidth, int imgHeight, const Rect& srcRect,
+ SkBitmap* bitmap) = 0;
+
private:
CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer, Matrix4& texTransform,
- const Rect& srcRect, SkBitmap* bitmap);
+ const Rect& srcRect, SkBitmap* bitmap);
};
class OpenGLReadbackImpl : public OpenGLReadback {
@@ -53,12 +55,13 @@ public:
* Copies the layer's contents into the provided bitmap.
*/
static bool copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer,
- SkBitmap* bitmap);
+ SkBitmap* bitmap);
protected:
virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
- int imgWidth, int imgHeight, const Rect& srcRect, SkBitmap* bitmap) override;
+ int imgWidth, int imgHeight, const Rect& srcRect,
+ SkBitmap* bitmap) override;
};
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 922ff7caecb8..4ddacc8a922d 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -26,27 +26,14 @@ namespace uirenderer {
class Outline {
public:
- enum class Type {
- None = 0,
- Empty = 1,
- ConvexPath = 2,
- RoundRect = 3
- };
-
- Outline()
- : mShouldClip(false)
- , mType(Type::None)
- , mRadius(0)
- , mAlpha(0.0f) {}
+ enum class Type { None = 0, Empty = 1, ConvexPath = 2, RoundRect = 3 };
+
+ Outline() : mShouldClip(false), mType(Type::None), mRadius(0), mAlpha(0.0f) {}
void setRoundRect(int left, int top, int right, int bottom, float radius, float alpha) {
mAlpha = alpha;
- if (mType == Type::RoundRect
- && left == mBounds.left
- && right == mBounds.right
- && top == mBounds.top
- && bottom == mBounds.bottom
- && radius == mRadius) {
+ if (mType == Type::RoundRect && left == mBounds.left && right == mBounds.right &&
+ top == mBounds.top && bottom == mBounds.bottom && radius == mRadius) {
// nothing to change, don't do any work
return;
}
@@ -55,11 +42,17 @@ public:
mBounds.set(left, top, right, bottom);
mRadius = radius;
+
+ // Reuse memory if previous outline was the same shape (rect or round rect).
+ if ( mPath.countVerbs() > 10) {
+ mPath.reset();
+ } else {
+ mPath.rewind();
+ }
+
// update mPath to reflect new outline
- mPath.reset();
if (MathUtils::isPositive(radius)) {
- mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom),
- radius, radius);
+ mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radius, radius);
} else {
mPath.addRect(left, top, right, bottom);
}
@@ -88,21 +81,13 @@ public:
mAlpha = 0.0f;
}
- bool isEmpty() const {
- return mType == Type::Empty;
- }
+ bool isEmpty() const { return mType == Type::Empty; }
- float getAlpha() const {
- return mAlpha;
- }
+ float getAlpha() const { return mAlpha; }
- void setShouldClip(bool clip) {
- mShouldClip = clip;
- }
+ void setShouldClip(bool clip) { mShouldClip = clip; }
- bool getShouldClip() const {
- return mShouldClip;
- }
+ bool getShouldClip() const { return mShouldClip; }
bool willClip() const {
// only round rect outlines can be used for clipping
@@ -129,17 +114,11 @@ public:
return &mPath;
}
- Type getType() const {
- return mType;
- }
+ Type getType() const { return mType; }
- const Rect& getBounds() const {
- return mBounds;
- }
+ const Rect& getBounds() const { return mBounds; }
- float getRadius() const {
- return mRadius;
- }
+ float getRadius() const { return mRadius; }
private:
bool mShouldClip;
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index b471e7850a99..c243dad01f04 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -21,8 +21,8 @@
#include "UvMapper.h"
#include "utils/MathUtils.h"
-#include <algorithm>
#include <utils/Log.h>
+#include <algorithm>
namespace android {
namespace uirenderer {
@@ -35,10 +35,9 @@ uint32_t Patch::getSize() const {
return verticesCount * sizeof(TextureVertex);
}
-Patch::Patch(const float bitmapWidth, const float bitmapHeight,
- float width, float height, const UvMapper& mapper, const Res_png_9patch* patch)
+Patch::Patch(const float bitmapWidth, const float bitmapHeight, float width, float height,
+ const UvMapper& mapper, const Res_png_9patch* patch)
: mColors(patch->getColors()) {
-
int8_t emptyQuads = 0;
const int8_t numColors = patch->numColors;
if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
@@ -121,8 +120,8 @@ Patch::Patch(const float bitmapWidth, const float bitmapHeight,
v1 += vOffset / bitmapHeight;
if (stepY > 0.0f) {
- generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX,
- width, bitmapWidth, quadCount);
+ generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX, width,
+ bitmapWidth, quadCount);
}
y1 = y2;
@@ -133,8 +132,8 @@ Patch::Patch(const float bitmapWidth, const float bitmapHeight,
if (previousStepY != bitmapHeight) {
y2 = height;
- generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX,
- width, bitmapWidth, quadCount);
+ generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX, width, bitmapWidth,
+ quadCount);
}
if (verticesCount != maxVertices) {
@@ -144,9 +143,9 @@ Patch::Patch(const float bitmapWidth, const float bitmapHeight,
}
}
-void Patch::generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
- float y1, float y2, float v1, float v2, float stretchX, float rescaleX,
- float width, float bitmapWidth, uint32_t& quadCount) {
+void Patch::generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex, float y1,
+ float y2, float v1, float v2, float stretchX, float rescaleX, float width,
+ float bitmapWidth, uint32_t& quadCount) {
float previousStepX = 0.0f;
float x1 = 0.0f;
@@ -184,8 +183,8 @@ void Patch::generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& v
}
}
-void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
- float u1, float v1, float u2, float v2, uint32_t& quadCount) {
+void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2, float u1,
+ float v1, float u2, float v2, uint32_t& quadCount) {
const uint32_t oldQuadCount = quadCount;
quadCount++;
@@ -226,5 +225,5 @@ void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, f
#endif
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index f04416ccabf9..a659ed227bec 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -39,9 +39,8 @@ struct TextureVertex;
class Patch {
public:
- Patch(const float bitmapWidth, const float bitmapHeight,
- float width, float height,
- const UvMapper& mapper, const Res_png_9patch* patch);
+ Patch(const float bitmapWidth, const float bitmapHeight, float width, float height,
+ const UvMapper& mapper, const Res_png_9patch* patch);
/**
* Returns the size of this patch's mesh in bytes.
@@ -58,17 +57,17 @@ public:
GLintptr textureOffset = 0;
private:
- void generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
- float y1, float y2, float v1, float v2, float stretchX, float rescaleX,
- float width, float bitmapWidth, uint32_t& quadCount);
- void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
- float u1, float v1, float u2, float v2, uint32_t& quadCount);
+ void generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex, float y1,
+ float y2, float v1, float v2, float stretchX, float rescaleX, float width,
+ float bitmapWidth, uint32_t& quadCount);
+ void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2, float u1,
+ float v1, float u2, float v2, uint32_t& quadCount);
const uint32_t* mColors;
UvMapper mUvMapper;
-}; // struct Patch
+}; // struct Patch
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_PATCH_H
+#endif // ANDROID_HWUI_PATCH_H
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 78c7eb9ad809..673d73c5475d 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -56,7 +56,7 @@ hash_t PatchCache::PatchDescription::hash() const {
}
int PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs,
- const PatchCache::PatchDescription& rhs) {
+ const PatchCache::PatchDescription& rhs) {
return memcmp(&lhs, &rhs, sizeof(PatchDescription));
}
@@ -115,7 +115,7 @@ void PatchCache::removeDeferred(Res_png_9patch* patch) {
void PatchCache::clearGarbage() {
Vector<patch_pair_t> patchesToRemove;
- { // scope for the mutex
+ { // scope for the mutex
Mutex::Autolock _l(mLock);
size_t count = mGarbage.size();
for (size_t i = 0; i < count; i++) {
@@ -123,7 +123,7 @@ void PatchCache::clearGarbage() {
remove(patchesToRemove, patch);
// A Res_png_9patch is actually an array of byte that's larger
// than sizeof(Res_png_9patch). It must be freed as an array.
- delete[] (int8_t*) patch;
+ delete[](int8_t*) patch;
}
mGarbage.clear();
}
@@ -153,8 +153,8 @@ void PatchCache::clearGarbage() {
}
void PatchCache::createVertexBuffer() {
- mRenderState.meshState().genOrUpdateMeshBuffer(&mMeshBuffer,
- mMaxSize, nullptr, GL_DYNAMIC_DRAW);
+ mRenderState.meshState().genOrUpdateMeshBuffer(&mMeshBuffer, mMaxSize, nullptr,
+ GL_DYNAMIC_DRAW);
mSize = 0;
mFreeBlocks = new BufferBlock(0, mMaxSize);
}
@@ -198,11 +198,11 @@ void PatchCache::setupMesh(Patch* newMesh) {
}
// Copy the 9patch mesh in the VBO
- newMesh->positionOffset = (GLintptr) (block->offset);
+ newMesh->positionOffset = (GLintptr)(block->offset);
newMesh->textureOffset = newMesh->positionOffset + kMeshTextureOffset;
mRenderState.meshState().updateMeshBufferSubData(mMeshBuffer, newMesh->positionOffset, size,
- newMesh->vertices.get());
+ newMesh->vertices.get());
// Remove the block since we've used it entirely
if (block->size == size) {
@@ -223,15 +223,15 @@ void PatchCache::setupMesh(Patch* newMesh) {
static const UvMapper sIdentity;
-const Patch* PatchCache::get( const uint32_t bitmapWidth, const uint32_t bitmapHeight,
- const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) {
-
+const Patch* PatchCache::get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
+ const float pixelWidth, const float pixelHeight,
+ const Res_png_9patch* patch) {
const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch);
const Patch* mesh = mCache.get(description);
if (!mesh) {
- Patch* newMesh = new Patch(bitmapWidth, bitmapHeight,
- pixelWidth, pixelHeight, sIdentity, patch);
+ Patch* newMesh =
+ new Patch(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, sIdentity, patch);
if (newMesh->vertices) {
setupMesh(newMesh);
@@ -260,5 +260,5 @@ void PatchCache::dumpFreeBlocks(const char* prefix) {
}
#endif
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index aa746c7dfa15..273c3f56f2cd 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -36,9 +36,9 @@ class Patch;
// Debug
#if DEBUG_PATCHES
- #define PATCH_LOGD(...) ALOGD(__VA_ARGS__)
+#define PATCH_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define PATCH_LOGD(...)
+#define PATCH_LOGD(...)
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -54,20 +54,14 @@ public:
~PatchCache();
const Patch* get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
- const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch);
+ const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch);
void clear();
- uint32_t getSize() const {
- return mSize;
- }
+ uint32_t getSize() const { return mSize; }
- uint32_t getMaxSize() const {
- return mMaxSize;
- }
+ uint32_t getMaxSize() const { return mMaxSize; }
- GLuint getMeshBuffer() const {
- return mMeshBuffer;
- }
+ GLuint getMeshBuffer() const { return mMeshBuffer; }
/**
* Removes the entries associated with the specified 9-patch. This is meant
@@ -81,18 +75,23 @@ public:
*/
void clearGarbage();
-
private:
struct PatchDescription {
- PatchDescription(): mPatch(nullptr), mBitmapWidth(0), mBitmapHeight(0),
- mPixelWidth(0), mPixelHeight(0) {
- }
+ PatchDescription()
+ : mPatch(nullptr)
+ , mBitmapWidth(0)
+ , mBitmapHeight(0)
+ , mPixelWidth(0)
+ , mPixelHeight(0) {}
PatchDescription(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
- const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch):
- mPatch(patch), mBitmapWidth(bitmapWidth), mBitmapHeight(bitmapHeight),
- mPixelWidth(pixelWidth), mPixelHeight(pixelHeight) {
- }
+ const float pixelWidth, const float pixelHeight,
+ const Res_png_9patch* patch)
+ : mPatch(patch)
+ , mBitmapWidth(bitmapWidth)
+ , mBitmapHeight(bitmapHeight)
+ , mPixelWidth(pixelWidth)
+ , mPixelHeight(pixelHeight) {}
hash_t hash() const;
@@ -100,27 +99,20 @@ private:
static int compare(const PatchDescription& lhs, const PatchDescription& rhs);
- bool operator==(const PatchDescription& other) const {
- return compare(*this, other) == 0;
- }
+ bool operator==(const PatchDescription& other) const { return compare(*this, other) == 0; }
- bool operator!=(const PatchDescription& other) const {
- return compare(*this, other) != 0;
- }
+ bool operator!=(const PatchDescription& other) const { return compare(*this, other) != 0; }
friend inline int strictly_order_type(const PatchDescription& lhs,
- const PatchDescription& rhs) {
+ const PatchDescription& rhs) {
return PatchDescription::compare(lhs, rhs) < 0;
}
- friend inline int compare_type(const PatchDescription& lhs,
- const PatchDescription& rhs) {
+ friend inline int compare_type(const PatchDescription& lhs, const PatchDescription& rhs) {
return PatchDescription::compare(lhs, rhs);
}
- friend inline hash_t hash_type(const PatchDescription& entry) {
- return entry.hash();
- }
+ friend inline hash_t hash_type(const PatchDescription& entry) { return entry.hash(); }
private:
const Res_png_9patch* mPatch;
@@ -129,7 +121,7 @@ private:
float mPixelWidth;
float mPixelHeight;
- }; // struct PatchDescription
+ }; // struct PatchDescription
/**
* A buffer block represents an empty range in the mesh buffer
@@ -139,14 +131,13 @@ private:
* to track available regions of memory in the VBO.
*/
struct BufferBlock {
- BufferBlock(uint32_t offset, uint32_t size): offset(offset), size(size), next(nullptr) {
- }
+ BufferBlock(uint32_t offset, uint32_t size) : offset(offset), size(size), next(nullptr) {}
uint32_t offset;
uint32_t size;
BufferBlock* next;
- }; // struct BufferBlock
+ }; // struct BufferBlock
typedef Pair<const PatchDescription*, Patch*> patch_pair_t;
@@ -174,7 +165,7 @@ private:
// Garbage tracking, required to handle GC events on the VM side
Vector<Res_png_9patch*> mGarbage;
mutable Mutex mLock;
-}; // class PatchCache
+}; // class PatchCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 8d4ae1b6622a..e67c5bddd354 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -46,13 +46,14 @@ static bool compareWidthHeight(const T& lhs, const T& rhs) {
}
static bool compareRoundRects(const PathDescription::Shape::RoundRect& lhs,
- const PathDescription::Shape::RoundRect& rhs) {
+ const PathDescription::Shape::RoundRect& rhs) {
return compareWidthHeight(lhs, rhs) && lhs.mRx == rhs.mRx && lhs.mRy == rhs.mRy;
}
-static bool compareArcs(const PathDescription::Shape::Arc& lhs, const PathDescription::Shape::Arc& rhs) {
+static bool compareArcs(const PathDescription::Shape::Arc& lhs,
+ const PathDescription::Shape::Arc& rhs) {
return compareWidthHeight(lhs, rhs) && lhs.mStartAngle == rhs.mStartAngle &&
- lhs.mSweepAngle == rhs.mSweepAngle && lhs.mUseCenter == rhs.mUseCenter;
+ lhs.mSweepAngle == rhs.mSweepAngle && lhs.mUseCenter == rhs.mUseCenter;
}
///////////////////////////////////////////////////////////////////////////////
@@ -91,7 +92,7 @@ hash_t PathDescription::hash() const {
hash = JenkinsHashMix(hash, android::hash_type(miter));
hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
hash = JenkinsHashMix(hash, android::hash_type(pathEffect));
- hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape));
+ hash = JenkinsHashMixBytes(hash, (uint8_t*)&shape, sizeof(Shape));
return JenkinsHashWhiten(hash);
}
@@ -126,7 +127,7 @@ bool PathDescription::operator==(const PathDescription& rhs) const {
///////////////////////////////////////////////////////////////////////////////
static void computePathBounds(const SkPath* path, const SkPaint* paint, PathTexture* texture,
- uint32_t& width, uint32_t& height) {
+ uint32_t& width, uint32_t& height) {
const SkRect& bounds = path->getBounds();
const float pathWidth = std::max(bounds.width(), 1.0f);
const float pathHeight = std::max(bounds.height(), 1.0f);
@@ -134,7 +135,7 @@ static void computePathBounds(const SkPath* path, const SkPaint* paint, PathText
texture->left = floorf(bounds.fLeft);
texture->top = floorf(bounds.fTop);
- texture->offset = (int) floorf(std::max(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
+ texture->offset = (int)floorf(std::max(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
width = uint32_t(pathWidth + texture->offset * 2.0 + 0.5);
height = uint32_t(pathHeight + texture->offset * 2.0 + 0.5);
@@ -152,12 +153,12 @@ static void initPaint(SkPaint& paint) {
}
static sk_sp<Bitmap> drawPath(const SkPath* path, const SkPaint* paint, PathTexture* texture,
- uint32_t maxTextureSize) {
+ uint32_t maxTextureSize) {
uint32_t width, height;
computePathBounds(path, paint, texture, width, height);
if (width > maxTextureSize || height > maxTextureSize) {
- ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)",
- width, height, maxTextureSize, maxTextureSize);
+ ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", width, height,
+ maxTextureSize, maxTextureSize);
return nullptr;
}
@@ -230,13 +231,13 @@ void PathCache::removeTexture(PathTexture* texture) {
// to the cache and the size wasn't increased
if (size > mSize) {
ALOGE("Removing path texture of size %d will leave "
- "the cache in an inconsistent state", size);
+ "the cache in an inconsistent state",
+ size);
}
mSize -= size;
}
- PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d",
- texture->id, size, mSize);
+ PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d", texture->id, size, mSize);
if (mDebugEnabled) {
ALOGD("Shape deleted, size = %d", size);
}
@@ -258,14 +259,16 @@ void PathCache::purgeCache(uint32_t width, uint32_t height) {
void PathCache::trim() {
while (mSize > mMaxSize || mCache.size() > PATH_CACHE_COUNT_LIMIT) {
- LOG_ALWAYS_FATAL_IF(!mCache.size(), "Inconsistent mSize! Ran out of items to remove!"
- " mSize = %u, mMaxSize = %u", mSize, mMaxSize);
+ LOG_ALWAYS_FATAL_IF(!mCache.size(),
+ "Inconsistent mSize! Ran out of items to remove!"
+ " mSize = %u, mMaxSize = %u",
+ mSize, mMaxSize);
mCache.removeOldest();
}
}
-PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *path,
- const SkPaint* paint) {
+PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath* path,
+ const SkPaint* paint) {
ATRACE_NAME("Generate Path Texture");
PathTexture* texture = new PathTexture(Caches::getInstance(), path->getGenerationID());
@@ -280,8 +283,8 @@ PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *p
return texture;
}
-void PathCache::generateTexture(const PathDescription& entry, Bitmap& bitmap,
- PathTexture* texture, bool addToCache) {
+void PathCache::generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture,
+ bool addToCache) {
generateTexture(bitmap, texture);
// Note here that we upload to a texture even if it's bigger than mMaxSize.
@@ -289,8 +292,7 @@ void PathCache::generateTexture(const PathDescription& entry, Bitmap& bitmap,
// immediately on trim, or on any other Path entering the cache.
uint32_t size = texture->width() * texture->height();
mSize += size;
- PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d",
- texture->id, size, mSize);
+ PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d", texture->id, size, mSize);
if (mDebugEnabled) {
ALOGD("Shape created, size = %d", size);
}
@@ -313,9 +315,8 @@ void PathCache::generateTexture(Bitmap& bitmap, Texture* texture) {
// Path precaching
///////////////////////////////////////////////////////////////////////////////
-PathCache::PathProcessor::PathProcessor(Caches& caches):
- TaskProcessor<sk_sp<Bitmap> >(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) {
-}
+PathCache::PathProcessor::PathProcessor(Caches& caches)
+ : TaskProcessor<sk_sp<Bitmap> >(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) {}
void PathCache::PathProcessor::onProcess(const sp<Task<sk_sp<Bitmap> > >& task) {
PathTask* t = static_cast<PathTask*>(task.get());
@@ -336,7 +337,7 @@ void PathCache::removeDeferred(const SkPath* path) {
void PathCache::clearGarbage() {
Vector<PathDescription> pathsToRemove;
- { // scope for the mutex
+ { // scope for the mutex
Mutex::Autolock l(mLock);
for (const uint32_t generationID : mGarbage) {
LruCache<PathDescription, PathTexture*>::Iterator iter(mCache);
@@ -433,8 +434,8 @@ void PathCache::precache(const SkPath* path, const SkPaint* paint) {
// Rounded rects
///////////////////////////////////////////////////////////////////////////////
-PathTexture* PathCache::getRoundRect(float width, float height,
- float rx, float ry, const SkPaint* paint) {
+PathTexture* PathCache::getRoundRect(float width, float height, float rx, float ry,
+ const SkPaint* paint) {
PathDescription entry(ShapeType::RoundRect, paint);
entry.shape.roundRect.mWidth = width;
entry.shape.roundRect.mHeight = height;
@@ -525,8 +526,8 @@ PathTexture* PathCache::getRect(float width, float height, const SkPaint* paint)
// Arcs
///////////////////////////////////////////////////////////////////////////////
-PathTexture* PathCache::getArc(float width, float height,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
+PathTexture* PathCache::getArc(float width, float height, float startAngle, float sweepAngle,
+ bool useCenter, const SkPaint* paint) {
PathDescription entry(ShapeType::Arc, paint);
entry.shape.arc.mWidth = width;
entry.shape.arc.mHeight = height;
@@ -554,5 +555,5 @@ PathTexture* PathCache::getArc(float width, float height,
return texture;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 7bd190df951b..28c8bbb8ca6e 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -47,9 +47,9 @@ class Caches;
// Debug
#if DEBUG_PATHS
- #define PATH_LOGD(...) ALOGD(__VA_ARGS__)
+#define PATH_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define PATH_LOGD(...)
+#define PATH_LOGD(...)
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -57,11 +57,10 @@ class Caches;
///////////////////////////////////////////////////////////////////////////////
struct PathTexture;
-class PathTask: public Task<sk_sp<Bitmap>> {
+class PathTask : public Task<sk_sp<Bitmap>> {
public:
- PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture):
- path(*path), paint(*paint), texture(texture) {
- }
+ PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture)
+ : path(*path), paint(*paint), texture(texture) {}
// copied, since input path not guaranteed to survive for duration of task
const SkPath path;
@@ -74,15 +73,10 @@ public:
/**
* Alpha texture used to represent a path.
*/
-struct PathTexture: public Texture {
- PathTexture(Caches& caches, int generation)
- : Texture(caches) {
- this->generation = generation;
- }
+struct PathTexture : public Texture {
+ PathTexture(Caches& caches, int generation) : Texture(caches) { this->generation = generation; }
- ~PathTexture() {
- clearTask();
- }
+ ~PathTexture() { clearTask(); }
/**
* Left coordinate of the path bounds.
@@ -97,13 +91,9 @@ struct PathTexture: public Texture {
*/
float offset = 0;
- sp<PathTask> task() const {
- return mTask;
- }
+ sp<PathTask> task() const { return mTask; }
- void setTask(const sp<PathTask>& task) {
- mTask = task;
- }
+ void setTask(const sp<PathTask>& task) { mTask = task; }
void clearTask() {
if (mTask != nullptr) {
@@ -113,17 +103,9 @@ struct PathTexture: public Texture {
private:
sp<PathTask> mTask;
-}; // struct PathTexture
-
-enum class ShapeType {
- None,
- Rect,
- RoundRect,
- Circle,
- Oval,
- Arc,
- Path
-};
+}; // struct PathTexture
+
+enum class ShapeType { None, Rect, RoundRect, Circle, Oval, Arc, Path };
struct PathDescription {
HASHABLE_TYPE(PathDescription);
@@ -173,7 +155,7 @@ struct PathDescription {
* Any texture added to the cache causing the cache to grow beyond the maximum
* allowed size will also cause the oldest texture to be kicked out.
*/
-class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> {
+class PathCache : public OnEntryRemoved<PathDescription, PathTexture*> {
public:
PathCache();
~PathCache();
@@ -203,9 +185,9 @@ public:
PathTexture* getOval(float width, float height, const SkPaint* paint);
PathTexture* getRect(float width, float height, const SkPaint* paint);
PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
- bool useCenter, const SkPaint* paint);
+ bool useCenter, const SkPaint* paint);
PathTexture* get(const SkPath* path, const SkPaint* paint);
- void remove(const SkPath* path, const SkPaint* paint);
+ void remove(const SkPath* path, const SkPaint* paint);
/**
* Removes the specified path. This is meant to be called from threads
@@ -234,19 +216,16 @@ public:
void precache(const SkPath* path, const SkPaint* paint);
private:
- PathTexture* addTexture(const PathDescription& entry,
- const SkPath *path, const SkPaint* paint);
+ PathTexture* addTexture(const PathDescription& entry, const SkPath* path, const SkPaint* paint);
/**
* Generates the texture from a bitmap into the specified texture structure.
*/
void generateTexture(Bitmap& bitmap, Texture* texture);
void generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture,
- bool addToCache = true);
+ bool addToCache = true);
- PathTexture* get(const PathDescription& entry) {
- return mCache.get(entry);
- }
+ PathTexture* get(const PathDescription& entry) { return mCache.get(entry); }
/**
* Ensures there is enough space in the cache for a texture of the specified
@@ -258,13 +237,12 @@ private:
void init();
-
- class PathProcessor: public TaskProcessor<sk_sp<Bitmap> > {
+ class PathProcessor : public TaskProcessor<sk_sp<Bitmap>> {
public:
explicit PathProcessor(Caches& caches);
- ~PathProcessor() { }
+ ~PathProcessor() {}
- virtual void onProcess(const sp<Task<sk_sp<Bitmap> > >& task) override;
+ virtual void onProcess(const sp<Task<sk_sp<Bitmap>>>& task) override;
private:
uint32_t mMaxTextureSize;
@@ -281,9 +259,9 @@ private:
std::vector<uint32_t> mGarbage;
mutable Mutex mLock;
-}; // class PathCache
+}; // class PathCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_PATH_CACHE_H
+#endif // ANDROID_HWUI_PATH_CACHE_H
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp
index 2179f146115a..47fcca92bcca 100644
--- a/libs/hwui/PathParser.cpp
+++ b/libs/hwui/PathParser.cpp
@@ -19,9 +19,9 @@
#include "jni.h"
#include <errno.h>
+#include <stdlib.h>
#include <utils/Log.h>
#include <sstream>
-#include <stdlib.h>
#include <string>
#include <vector>
@@ -36,8 +36,8 @@ static size_t nextStart(const char* s, size_t length, size_t startIndex) {
// used for floating point numbers' scientific notation.
// Therefore, when searching for next command, we should ignore 'e'
// and 'E'.
- if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
- && c != 'e' && c != 'E') {
+ if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0)) && c != 'e' &&
+ c != 'E') {
return index;
}
index++;
@@ -52,7 +52,8 @@ static size_t nextStart(const char* s, size_t length, size_t startIndex) {
* @param result the result of the extraction, including the position of the
* the starting position of next number, whether it is ending with a '-'.
*/
-static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s, int start, int end) {
+static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s, int start,
+ int end) {
// Now looking for ' ', ',', '.' or '-' from the start.
int currentIndex = start;
bool foundSeparator = false;
@@ -64,30 +65,30 @@ static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s
isExponential = false;
char currentChar = s[currentIndex];
switch (currentChar) {
- case ' ':
- case ',':
- foundSeparator = true;
- break;
- case '-':
- // The negative sign following a 'e' or 'E' is not a separator.
- if (currentIndex != start && !isPrevExponential) {
- foundSeparator = true;
- *outEndWithNegOrDot = true;
- }
- break;
- case '.':
- if (!secondDot) {
- secondDot = true;
- } else {
- // This is the second dot, and it is considered as a separator.
+ case ' ':
+ case ',':
foundSeparator = true;
- *outEndWithNegOrDot = true;
- }
- break;
- case 'e':
- case 'E':
- isExponential = true;
- break;
+ break;
+ case '-':
+ // The negative sign following a 'e' or 'E' is not a separator.
+ if (currentIndex != start && !isPrevExponential) {
+ foundSeparator = true;
+ *outEndWithNegOrDot = true;
+ }
+ break;
+ case '.':
+ if (!secondDot) {
+ secondDot = true;
+ } else {
+ // This is the second dot, and it is considered as a separator.
+ foundSeparator = true;
+ *outEndWithNegOrDot = true;
+ }
+ break;
+ case 'e':
+ case 'E':
+ isExponential = true;
+ break;
}
if (foundSeparator) {
break;
@@ -98,7 +99,8 @@ static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s
*outEndPosition = currentIndex;
}
-static float parseFloat(PathParser::ParseResult* result, const char* startPtr, size_t expectedLength) {
+static float parseFloat(PathParser::ParseResult* result, const char* startPtr,
+ size_t expectedLength) {
char* endPtr = NULL;
float currentValue = strtof(startPtr, &endPtr);
if ((currentValue == HUGE_VALF || currentValue == -HUGE_VALF) && errno == ERANGE) {
@@ -122,8 +124,7 @@ static float parseFloat(PathParser::ParseResult* result, const char* startPtr, s
* @return true on success
*/
static void getFloats(std::vector<float>* outPoints, PathParser::ParseResult* result,
- const char* pathStr, int start, int end) {
-
+ const char* pathStr, int start, int end) {
if (pathStr[start] == 'z' || pathStr[start] == 'Z') {
return;
}
@@ -138,8 +139,7 @@ static void getFloats(std::vector<float>* outPoints, PathParser::ParseResult* re
extract(&endPosition, &endWithNegOrDot, pathStr, startPosition, end);
if (startPosition < endPosition) {
- float currentValue = parseFloat(result, &pathStr[startPosition],
- end - startPosition);
+ float currentValue = parseFloat(result, &pathStr[startPosition], end - startPosition);
if (result->failureOccurred) {
return;
}
@@ -156,14 +156,67 @@ static void getFloats(std::vector<float>* outPoints, PathParser::ParseResult* re
return;
}
-bool PathParser::isVerbValid(char verb) {
- verb = tolower(verb);
- return verb == 'a' || verb == 'c' || verb == 'h' || verb == 'l' || verb == 'm' || verb == 'q'
- || verb == 's' || verb == 't' || verb == 'v' || verb == 'z';
+void PathParser::validateVerbAndPoints(char verb, size_t points, PathParser::ParseResult* result) {
+ size_t numberOfPointsExpected = -1;
+ switch (verb) {
+ case 'z':
+ case 'Z':
+ numberOfPointsExpected = 0;
+ break;
+ case 'm':
+ case 'l':
+ case 't':
+ case 'M':
+ case 'L':
+ case 'T':
+ numberOfPointsExpected = 2;
+ break;
+ case 'h':
+ case 'v':
+ case 'H':
+ case 'V':
+ numberOfPointsExpected = 1;
+ break;
+ case 'c':
+ case 'C':
+ numberOfPointsExpected = 6;
+ break;
+ case 's':
+ case 'q':
+ case 'S':
+ case 'Q':
+ numberOfPointsExpected = 4;
+ break;
+ case 'a':
+ case 'A':
+ numberOfPointsExpected = 7;
+ break;
+ default:
+ result->failureOccurred = true;
+ result->failureMessage += verb;
+ result->failureMessage += " is not a valid verb. ";
+ return;
+ }
+ if (numberOfPointsExpected == 0 && points == 0) {
+ return;
+ }
+ if (numberOfPointsExpected > 0 && points % numberOfPointsExpected == 0) {
+ return;
+ }
+
+ result->failureOccurred = true;
+ result->failureMessage += verb;
+ result->failureMessage += " needs to be followed by ";
+ if (numberOfPointsExpected > 0) {
+ result->failureMessage += "a multiple of ";
+ }
+ result->failureMessage += std::to_string(numberOfPointsExpected)
+ + " floats. However, " + std::to_string(points)
+ + " float(s) are found. ";
}
void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result,
- const char* pathStr, size_t strLen) {
+ const char* pathStr, size_t strLen) {
if (pathStr == NULL) {
result->failureOccurred = true;
result->failureMessage = "Path string cannot be NULL.";
@@ -186,13 +239,11 @@ void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result,
end = nextStart(pathStr, strLen, end);
std::vector<float> points;
getFloats(&points, result, pathStr, start, end);
- if (!isVerbValid(pathStr[start])) {
- result->failureOccurred = true;
- result->failureMessage = "Invalid pathData. Failure occurred at position "
- + std::to_string(start) + " of path: " + pathStr;
- }
- // If either verb or points is not valid, return immediately.
+ validateVerbAndPoints(pathStr[start], points.size(), result);
if (result->failureOccurred) {
+ // If either verb or points is not valid, return immediately.
+ result->failureMessage += "Failure occurred at position " +
+ std::to_string(start) + " of path: " + pathStr;
return;
}
data->verbs.push_back(pathStr[start]);
@@ -203,10 +254,11 @@ void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result,
}
if ((end - start) == 1 && start < strLen) {
- if (!isVerbValid(pathStr[start])) {
- result->failureOccurred = true;
- result->failureMessage = "Invalid pathData. Failure occurred at position "
- + std::to_string(start) + " of path: " + pathStr;
+ validateVerbAndPoints(pathStr[start], 0, result);
+ if (result->failureOccurred) {
+ // If either verb or points is not valid, return immediately.
+ result->failureMessage += "Failure occurred at position " +
+ std::to_string(start) + " of path: " + pathStr;
return;
}
data->verbs.push_back(pathStr[start]);
@@ -235,7 +287,8 @@ void PathParser::dump(const PathData& data) {
ALOGD("points are : %s", os.str().c_str());
}
-void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result, const char* pathStr, size_t strLen) {
+void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result, const char* pathStr,
+ size_t strLen) {
PathData pathData;
getPathDataFromAsciiString(&pathData, result, pathStr, strLen);
if (result->failureOccurred) {
@@ -252,5 +305,5 @@ void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result,
return;
}
-}; // namespace uirenderer
-}; //namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h
index 5578e8d42e2f..474eb97b53c6 100644
--- a/libs/hwui/PathParser.h
+++ b/libs/hwui/PathParser.h
@@ -20,16 +20,15 @@
#include "VectorDrawable.h"
#include "utils/VectorDrawableUtils.h"
-#include <jni.h>
#include <android/log.h>
#include <cutils/compiler.h>
+#include <jni.h>
#include <string>
namespace android {
namespace uirenderer {
-
class PathParser {
public:
struct ANDROID_API ParseResult {
@@ -40,13 +39,13 @@ public:
* Parse the string literal and create a Skia Path. Return true on success.
*/
ANDROID_API static void parseAsciiStringForSkPath(SkPath* outPath, ParseResult* result,
- const char* pathStr, size_t strLength);
+ const char* pathStr, size_t strLength);
ANDROID_API static void getPathDataFromAsciiString(PathData* outData, ParseResult* result,
- const char* pathStr, size_t strLength);
+ const char* pathStr, size_t strLength);
static void dump(const PathData& data);
- static bool isVerbValid(char verb);
+ static void validateVerbAndPoints(char verb, size_t points, ParseResult* result);
};
-}; // namespace uirenderer
-}; // namespace android
-#endif //ANDROID_HWUI_PATHPARSER_H
+}; // namespace uirenderer
+}; // namespace android
+#endif // ANDROID_HWUI_PATHPARSER_H
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 64b2c4564d7b..973b1d14b77e 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -18,13 +18,12 @@
#define VERTEX_DEBUG 0
#if VERTEX_DEBUG
-#define DEBUG_DUMP_ALPHA_BUFFER() \
- for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { \
- ALOGD("point %d at %f %f, alpha %f", \
- i, buffer[i].x, buffer[i].y, buffer[i].alpha); \
+#define DEBUG_DUMP_ALPHA_BUFFER() \
+ for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { \
+ ALOGD("point %d at %f %f, alpha %f", i, buffer[i].x, buffer[i].y, buffer[i].alpha); \
}
-#define DEBUG_DUMP_BUFFER() \
- for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { \
+#define DEBUG_DUMP_BUFFER() \
+ for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { \
ALOGD("point %d at %f %f", i, buffer[i].x, buffer[i].y); \
}
#else
@@ -41,13 +40,13 @@
#include <algorithm>
-#include <SkPath.h>
+#include <SkGeometry.h> // WARNING: Internal Skia Header
#include <SkPaint.h>
+#include <SkPath.h>
#include <SkPoint.h>
-#include <SkGeometry.h> // WARNING: Internal Skia Header
-#include <stdlib.h>
#include <stdint.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <utils/Log.h>
@@ -64,8 +63,8 @@ namespace uirenderer {
/**
* Extracts the x and y scale from the transform as positive values, and clamps them
*/
-void PathTessellator::extractTessellationScales(const Matrix4& transform,
- float* scaleX, float* scaleY) {
+void PathTessellator::extractTessellationScales(const Matrix4& transform, float* scaleX,
+ float* scaleY) {
if (CC_LIKELY(transform.isPureTranslate())) {
*scaleX = 1.0f;
*scaleY = 1.0f;
@@ -98,9 +97,12 @@ inline static Vector2 totalOffsetFromNormals(const Vector2& normalA, const Vecto
*/
struct PaintInfo {
public:
- PaintInfo(const SkPaint* paint, const mat4& transform) :
- style(paint->getStyle()), cap(paint->getStrokeCap()), isAA(paint->isAntiAlias()),
- halfStrokeWidth(paint->getStrokeWidth() * 0.5f), maxAlpha(1.0f) {
+ PaintInfo(const SkPaint* paint, const mat4& transform)
+ : style(paint->getStyle())
+ , cap(paint->getStrokeCap())
+ , isAA(paint->isAntiAlias())
+ , halfStrokeWidth(paint->getStrokeWidth() * 0.5f)
+ , maxAlpha(1.0f) {
// compute inverse scales
if (CC_LIKELY(transform.isPureTranslate())) {
inverseScaleX = 1.0f;
@@ -113,7 +115,7 @@ public:
}
if (isAA && halfStrokeWidth != 0 && inverseScaleX == inverseScaleY &&
- 2 * halfStrokeWidth < inverseScaleX) {
+ 2 * halfStrokeWidth < inverseScaleX) {
// AA, with non-hairline stroke, width < 1 pixel. Scale alpha and treat as hairline.
maxAlpha *= (2 * halfStrokeWidth) / inverseScaleX;
halfStrokeWidth = 0.0f;
@@ -171,17 +173,17 @@ public:
if (halfStrokeWidth == 0) {
// hairline, outset by (0.5f + fudge factor) in post-scaling space
bounds->outset(fabs(inverseScaleX) * (0.5f + Vertex::GeometryFudgeFactor()),
- fabs(inverseScaleY) * (0.5f + Vertex::GeometryFudgeFactor()));
+ fabs(inverseScaleY) * (0.5f + Vertex::GeometryFudgeFactor()));
} else {
// non hairline, outset by half stroke width pre-scaled, and fudge factor post scaled
bounds->outset(halfStrokeWidth + fabs(inverseScaleX) * Vertex::GeometryFudgeFactor(),
- halfStrokeWidth + fabs(inverseScaleY) * Vertex::GeometryFudgeFactor());
+ halfStrokeWidth + fabs(inverseScaleY) * Vertex::GeometryFudgeFactor());
}
}
};
void getFillVerticesFromPerimeter(const std::vector<Vertex>& perimeter,
- VertexBuffer& vertexBuffer) {
+ VertexBuffer& vertexBuffer) {
Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size());
int currentIndex = 0;
@@ -206,7 +208,8 @@ void getFillVerticesFromPerimeter(const std::vector<Vertex>& perimeter,
* (for a total of perimeter.size() * 2 + 2 vertices)
*/
void getStrokeVerticesFromPerimeter(const PaintInfo& paintInfo,
- const std::vector<Vertex>& perimeter, VertexBuffer& vertexBuffer) {
+ const std::vector<Vertex>& perimeter,
+ VertexBuffer& vertexBuffer) {
Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size() * 2 + 2);
int currentIndex = 0;
@@ -222,13 +225,11 @@ void getStrokeVerticesFromPerimeter(const PaintInfo& paintInfo,
Vector2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
paintInfo.scaleOffsetForStrokeWidth(totalOffset);
- Vertex::set(&buffer[currentIndex++],
- current->x + totalOffset.x,
- current->y + totalOffset.y);
+ Vertex::set(&buffer[currentIndex++], current->x + totalOffset.x,
+ current->y + totalOffset.y);
- Vertex::set(&buffer[currentIndex++],
- current->x - totalOffset.x,
- current->y - totalOffset.y);
+ Vertex::set(&buffer[currentIndex++], current->x - totalOffset.x,
+ current->y - totalOffset.y);
current = next;
lastNormal = nextNormal;
@@ -242,7 +243,8 @@ void getStrokeVerticesFromPerimeter(const PaintInfo& paintInfo,
}
static inline void storeBeginEnd(const PaintInfo& paintInfo, const Vertex& center,
- const Vector2& normal, Vertex* buffer, int& currentIndex, bool begin) {
+ const Vector2& normal, Vertex* buffer, int& currentIndex,
+ bool begin) {
Vector2 strokeOffset = normal;
paintInfo.scaleOffsetForStrokeWidth(strokeOffset);
@@ -264,7 +266,8 @@ static inline void storeBeginEnd(const PaintInfo& paintInfo, const Vertex& cente
* 2 - can zig-zag across 'extra' vertices at either end, to create round caps
*/
void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo,
- const std::vector<Vertex>& vertices, VertexBuffer& vertexBuffer) {
+ const std::vector<Vertex>& vertices,
+ VertexBuffer& vertexBuffer) {
const int extra = paintInfo.capExtraDivisions();
const int allocSize = (vertices.size() + extra) * 2;
Vertex* buffer = vertexBuffer.alloc<Vertex>(allocSize);
@@ -272,12 +275,9 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo,
const int lastIndex = vertices.size() - 1;
if (extra > 0) {
// tessellate both round caps
- float beginTheta = atan2(
- - (vertices[0].x - vertices[1].x),
- vertices[0].y - vertices[1].y);
- float endTheta = atan2(
- - (vertices[lastIndex].x - vertices[lastIndex - 1].x),
- vertices[lastIndex].y - vertices[lastIndex - 1].y);
+ float beginTheta = atan2(-(vertices[0].x - vertices[1].x), vertices[0].y - vertices[1].y);
+ float endTheta = atan2(-(vertices[lastIndex].x - vertices[lastIndex - 1].x),
+ vertices[lastIndex].y - vertices[lastIndex - 1].y);
const float dTheta = PI / (extra + 1);
int capOffset;
@@ -291,16 +291,15 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo,
beginTheta += dTheta;
Vector2 beginRadialOffset = {cosf(beginTheta), sinf(beginTheta)};
paintInfo.scaleOffsetForStrokeWidth(beginRadialOffset);
- Vertex::set(&buffer[capOffset],
- vertices[0].x + beginRadialOffset.x,
- vertices[0].y + beginRadialOffset.y);
+ Vertex::set(&buffer[capOffset], vertices[0].x + beginRadialOffset.x,
+ vertices[0].y + beginRadialOffset.y);
endTheta += dTheta;
Vector2 endRadialOffset = {cosf(endTheta), sinf(endTheta)};
paintInfo.scaleOffsetForStrokeWidth(endRadialOffset);
Vertex::set(&buffer[allocSize - 1 - capOffset],
- vertices[lastIndex].x + endRadialOffset.x,
- vertices[lastIndex].y + endRadialOffset.y);
+ vertices[lastIndex].x + endRadialOffset.x,
+ vertices[lastIndex].y + endRadialOffset.y);
}
}
@@ -317,7 +316,7 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo,
Vector2 nextNormal = {next->y - current->y, current->x - next->x};
nextNormal.normalize();
- Vector2 strokeOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+ Vector2 strokeOffset = totalOffsetFromNormals(lastNormal, nextNormal);
paintInfo.scaleOffsetForStrokeWidth(strokeOffset);
Vector2 center = {current->x, current->y};
@@ -344,8 +343,8 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo,
* 3 - zig zag back and forth inside the shape to fill it (using perimeter.size() vertices)
*/
void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo,
- const std::vector<Vertex>& perimeter, VertexBuffer& vertexBuffer,
- float maxAlpha = 1.0f) {
+ const std::vector<Vertex>& perimeter,
+ VertexBuffer& vertexBuffer, float maxAlpha = 1.0f) {
AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(perimeter.size() * 3 + 2);
// generate alpha points - fill Alpha vertex gaps in between each point with
@@ -362,16 +361,13 @@ void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo,
// AA point offset from original point is that point's normal, such that each side is offset
// by .5 pixels
- Vector2 totalOffset = paintInfo.deriveAAOffset(totalOffsetFromNormals(lastNormal, nextNormal));
+ Vector2 totalOffset =
+ paintInfo.deriveAAOffset(totalOffsetFromNormals(lastNormal, nextNormal));
- AlphaVertex::set(&buffer[currentIndex++],
- current->x + totalOffset.x,
- current->y + totalOffset.y,
- 0.0f);
- AlphaVertex::set(&buffer[currentIndex++],
- current->x - totalOffset.x,
- current->y - totalOffset.y,
- maxAlpha);
+ AlphaVertex::set(&buffer[currentIndex++], current->x + totalOffset.x,
+ current->y + totalOffset.y, 0.0f);
+ AlphaVertex::set(&buffer[currentIndex++], current->x - totalOffset.x,
+ current->y - totalOffset.y, maxAlpha);
current = next;
lastNormal = nextNormal;
@@ -404,12 +400,11 @@ void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo,
* getStrokeVerticesFromUnclosedVerticesAA() below.
*/
inline static void storeCapAA(const PaintInfo& paintInfo, const std::vector<Vertex>& vertices,
- AlphaVertex* buffer, bool isFirst, Vector2 normal, int offset) {
+ AlphaVertex* buffer, bool isFirst, Vector2 normal, int offset) {
const int extra = paintInfo.capExtraDivisions();
const int extraOffset = (extra + 1) / 2;
- const int capIndex = isFirst
- ? 2 * offset + 6 + 2 * (extra + extraOffset)
- : offset + 2 + 2 * extraOffset;
+ const int capIndex =
+ isFirst ? 2 * offset + 6 + 2 * (extra + extraOffset) : offset + 2 + 2 * extraOffset;
if (isFirst) normal *= -1;
// TODO: this normal should be scaled by radialScale if extra != 0, see totalOffsetFromNormals()
@@ -437,26 +432,18 @@ inline static void storeCapAA(const PaintInfo& paintInfo, const std::vector<Vert
referencePoint += rotated;
}
- AlphaVertex::set(&buffer[capIndex + 0],
- referencePoint.x + outerOffset.x + capAAOffset.x,
- referencePoint.y + outerOffset.y + capAAOffset.y,
- 0.0f);
- AlphaVertex::set(&buffer[capIndex + 1],
- referencePoint.x + innerOffset.x - capAAOffset.x,
- referencePoint.y + innerOffset.y - capAAOffset.y,
- paintInfo.maxAlpha);
+ AlphaVertex::set(&buffer[capIndex + 0], referencePoint.x + outerOffset.x + capAAOffset.x,
+ referencePoint.y + outerOffset.y + capAAOffset.y, 0.0f);
+ AlphaVertex::set(&buffer[capIndex + 1], referencePoint.x + innerOffset.x - capAAOffset.x,
+ referencePoint.y + innerOffset.y - capAAOffset.y, paintInfo.maxAlpha);
bool isRound = paintInfo.cap == SkPaint::kRound_Cap;
const int postCapIndex = (isRound && isFirst) ? (2 * extraOffset - 2) : capIndex + (2 * extra);
- AlphaVertex::set(&buffer[postCapIndex + 2],
- referencePoint.x - outerOffset.x + capAAOffset.x,
- referencePoint.y - outerOffset.y + capAAOffset.y,
- 0.0f);
- AlphaVertex::set(&buffer[postCapIndex + 3],
- referencePoint.x - innerOffset.x - capAAOffset.x,
- referencePoint.y - innerOffset.y - capAAOffset.y,
- paintInfo.maxAlpha);
+ AlphaVertex::set(&buffer[postCapIndex + 2], referencePoint.x - outerOffset.x + capAAOffset.x,
+ referencePoint.y - outerOffset.y + capAAOffset.y, 0.0f);
+ AlphaVertex::set(&buffer[postCapIndex + 3], referencePoint.x - innerOffset.x - capAAOffset.x,
+ referencePoint.y - innerOffset.y - capAAOffset.y, paintInfo.maxAlpha);
if (isRound) {
const float dTheta = PI / (extra + 1);
@@ -475,20 +462,18 @@ inline static void storeCapAA(const PaintInfo& paintInfo, const std::vector<Vert
AAOffset = paintInfo.deriveAAOffset(radialOffset);
paintInfo.scaleOffsetForStrokeWidth(radialOffset);
AlphaVertex::set(&buffer[capPerimIndex++],
- referencePoint.x + radialOffset.x + AAOffset.x,
- referencePoint.y + radialOffset.y + AAOffset.y,
- 0.0f);
+ referencePoint.x + radialOffset.x + AAOffset.x,
+ referencePoint.y + radialOffset.y + AAOffset.y, 0.0f);
AlphaVertex::set(&buffer[capPerimIndex++],
- referencePoint.x + radialOffset.x - AAOffset.x,
- referencePoint.y + radialOffset.y - AAOffset.y,
- paintInfo.maxAlpha);
+ referencePoint.x + radialOffset.x - AAOffset.x,
+ referencePoint.y + radialOffset.y - AAOffset.y, paintInfo.maxAlpha);
if (isFirst && i == extra - extraOffset) {
- //copy most recent two points to first two points
+ // copy most recent two points to first two points
buffer[0] = buffer[capPerimIndex - 2];
buffer[1] = buffer[capPerimIndex - 1];
- capPerimIndex = 2; // start writing the rest of the round cap at index 2
+ capPerimIndex = 2; // start writing the rest of the round cap at index 2
}
}
@@ -513,7 +498,7 @@ inline static void storeCapAA(const PaintInfo& paintInfo, const std::vector<Vert
if (isFirst) {
buffer[0] = buffer[postCapIndex + 2];
buffer[1] = buffer[postCapIndex + 3];
- buffer[postCapIndex + 4] = buffer[1]; // degenerate tris (the only two!)
+ buffer[postCapIndex + 4] = buffer[1]; // degenerate tris (the only two!)
buffer[postCapIndex + 5] = buffer[postCapIndex + 1];
} else {
buffer[6 * vertices.size()] = buffer[postCapIndex + 1];
@@ -574,8 +559,8 @@ or, for rounded caps:
= 2 + 6 * pts + 6 * roundDivs
*/
void getStrokeVerticesFromUnclosedVerticesAA(const PaintInfo& paintInfo,
- const std::vector<Vertex>& vertices, VertexBuffer& vertexBuffer) {
-
+ const std::vector<Vertex>& vertices,
+ VertexBuffer& vertexBuffer) {
const int extra = paintInfo.capExtraDivisions();
const int allocSize = 6 * vertices.size() + 2 + 6 * extra;
@@ -609,32 +594,20 @@ void getStrokeVerticesFromUnclosedVerticesAA(const PaintInfo& paintInfo,
Vector2 outerOffset = innerOffset + AAOffset;
innerOffset -= AAOffset;
- AlphaVertex::set(&buffer[currentAAOuterIndex++],
- current->x + outerOffset.x,
- current->y + outerOffset.y,
- 0.0f);
- AlphaVertex::set(&buffer[currentAAOuterIndex++],
- current->x + innerOffset.x,
- current->y + innerOffset.y,
- paintInfo.maxAlpha);
-
- AlphaVertex::set(&buffer[currentStrokeIndex++],
- current->x + innerOffset.x,
- current->y + innerOffset.y,
- paintInfo.maxAlpha);
- AlphaVertex::set(&buffer[currentStrokeIndex++],
- current->x - innerOffset.x,
- current->y - innerOffset.y,
- paintInfo.maxAlpha);
-
- AlphaVertex::set(&buffer[currentAAInnerIndex--],
- current->x - innerOffset.x,
- current->y - innerOffset.y,
- paintInfo.maxAlpha);
- AlphaVertex::set(&buffer[currentAAInnerIndex--],
- current->x - outerOffset.x,
- current->y - outerOffset.y,
- 0.0f);
+ AlphaVertex::set(&buffer[currentAAOuterIndex++], current->x + outerOffset.x,
+ current->y + outerOffset.y, 0.0f);
+ AlphaVertex::set(&buffer[currentAAOuterIndex++], current->x + innerOffset.x,
+ current->y + innerOffset.y, paintInfo.maxAlpha);
+
+ AlphaVertex::set(&buffer[currentStrokeIndex++], current->x + innerOffset.x,
+ current->y + innerOffset.y, paintInfo.maxAlpha);
+ AlphaVertex::set(&buffer[currentStrokeIndex++], current->x - innerOffset.x,
+ current->y - innerOffset.y, paintInfo.maxAlpha);
+
+ AlphaVertex::set(&buffer[currentAAInnerIndex--], current->x - innerOffset.x,
+ current->y - innerOffset.y, paintInfo.maxAlpha);
+ AlphaVertex::set(&buffer[currentAAInnerIndex--], current->x - outerOffset.x,
+ current->y - outerOffset.y, 0.0f);
current = next;
lastNormal = nextNormal;
@@ -646,9 +619,9 @@ void getStrokeVerticesFromUnclosedVerticesAA(const PaintInfo& paintInfo,
DEBUG_DUMP_ALPHA_BUFFER();
}
-
void getStrokeVerticesFromPerimeterAA(const PaintInfo& paintInfo,
- const std::vector<Vertex>& perimeter, VertexBuffer& vertexBuffer) {
+ const std::vector<Vertex>& perimeter,
+ VertexBuffer& vertexBuffer) {
AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * perimeter.size() + 8);
int offset = 2 * perimeter.size() + 3;
@@ -673,32 +646,20 @@ void getStrokeVerticesFromPerimeterAA(const PaintInfo& paintInfo,
Vector2 outerOffset = innerOffset + AAOffset;
innerOffset -= AAOffset;
- AlphaVertex::set(&buffer[currentAAOuterIndex++],
- current->x + outerOffset.x,
- current->y + outerOffset.y,
- 0.0f);
- AlphaVertex::set(&buffer[currentAAOuterIndex++],
- current->x + innerOffset.x,
- current->y + innerOffset.y,
- paintInfo.maxAlpha);
-
- AlphaVertex::set(&buffer[currentStrokeIndex++],
- current->x + innerOffset.x,
- current->y + innerOffset.y,
- paintInfo.maxAlpha);
- AlphaVertex::set(&buffer[currentStrokeIndex++],
- current->x - innerOffset.x,
- current->y - innerOffset.y,
- paintInfo.maxAlpha);
-
- AlphaVertex::set(&buffer[currentAAInnerIndex++],
- current->x - innerOffset.x,
- current->y - innerOffset.y,
- paintInfo.maxAlpha);
- AlphaVertex::set(&buffer[currentAAInnerIndex++],
- current->x - outerOffset.x,
- current->y - outerOffset.y,
- 0.0f);
+ AlphaVertex::set(&buffer[currentAAOuterIndex++], current->x + outerOffset.x,
+ current->y + outerOffset.y, 0.0f);
+ AlphaVertex::set(&buffer[currentAAOuterIndex++], current->x + innerOffset.x,
+ current->y + innerOffset.y, paintInfo.maxAlpha);
+
+ AlphaVertex::set(&buffer[currentStrokeIndex++], current->x + innerOffset.x,
+ current->y + innerOffset.y, paintInfo.maxAlpha);
+ AlphaVertex::set(&buffer[currentStrokeIndex++], current->x - innerOffset.x,
+ current->y - innerOffset.y, paintInfo.maxAlpha);
+
+ AlphaVertex::set(&buffer[currentAAInnerIndex++], current->x - innerOffset.x,
+ current->y - innerOffset.y, paintInfo.maxAlpha);
+ AlphaVertex::set(&buffer[currentAAInnerIndex++], current->x - outerOffset.x,
+ current->y - outerOffset.y, 0.0f);
current = next;
lastNormal = nextNormal;
@@ -720,8 +681,8 @@ void getStrokeVerticesFromPerimeterAA(const PaintInfo& paintInfo,
DEBUG_DUMP_ALPHA_BUFFER();
}
-void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
- const mat4& transform, VertexBuffer& vertexBuffer) {
+void PathTessellator::tessellatePath(const SkPath& path, const SkPaint* paint,
+ const mat4& transform, VertexBuffer& vertexBuffer) {
ATRACE_CALL();
const PaintInfo paintInfo(paint, transform);
@@ -742,9 +703,9 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
// force close if we're filling the path, since fill path expects closed perimeter.
bool forceClose = paintInfo.style != SkPaint::kStroke_Style;
PathApproximationInfo approximationInfo(threshInvScaleX, threshInvScaleY,
- OUTLINE_REFINE_THRESHOLD);
- bool wasClosed = approximatePathOutlineVertices(path, forceClose,
- approximationInfo, tempVertices);
+ OUTLINE_REFINE_THRESHOLD);
+ bool wasClosed =
+ approximatePathOutlineVertices(path, forceClose, approximationInfo, tempVertices);
if (!tempVertices.size()) {
// path was empty, return without allocating vertex buffer
@@ -753,8 +714,7 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
#if VERTEX_DEBUG
for (unsigned int i = 0; i < tempVertices.size(); i++) {
- ALOGD("orig path: point at %f %f",
- tempVertices[i].x, tempVertices[i].y);
+ ALOGD("orig path: point at %f %f", tempVertices[i].x, tempVertices[i].y);
}
#endif
@@ -790,8 +750,8 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
}
template <class TYPE>
-static void instanceVertices(VertexBuffer& srcBuffer, VertexBuffer& dstBuffer,
- const float* points, int count, Rect& bounds) {
+static void instanceVertices(VertexBuffer& srcBuffer, VertexBuffer& dstBuffer, const float* points,
+ int count, Rect& bounds) {
bounds.set(points[0], points[1], points[0], points[1]);
int numPoints = count / 2;
@@ -806,7 +766,7 @@ static void instanceVertices(VertexBuffer& srcBuffer, VertexBuffer& dstBuffer,
}
void PathTessellator::tessellatePoints(const float* points, int count, const SkPaint* paint,
- const mat4& transform, VertexBuffer& vertexBuffer) {
+ const mat4& transform, VertexBuffer& vertexBuffer) {
const PaintInfo paintInfo(paint, transform);
// determine point shape
@@ -823,7 +783,7 @@ void PathTessellator::tessellatePoints(const float* points, int count, const SkP
// calculate outline
std::vector<Vertex> outlineVertices;
PathApproximationInfo approximationInfo(paintInfo.inverseScaleX, paintInfo.inverseScaleY,
- OUTLINE_REFINE_THRESHOLD);
+ OUTLINE_REFINE_THRESHOLD);
approximatePathOutlineVertices(path, true, approximationInfo, outlineVertices);
if (!outlineVertices.size()) return;
@@ -847,7 +807,7 @@ void PathTessellator::tessellatePoints(const float* points, int count, const SkP
}
void PathTessellator::tessellateLines(const float* points, int count, const SkPaint* paint,
- const mat4& transform, VertexBuffer& vertexBuffer) {
+ const mat4& transform, VertexBuffer& vertexBuffer) {
ATRACE_CALL();
const PaintInfo paintInfo(paint, transform);
@@ -900,7 +860,7 @@ void PathTessellator::tessellateLines(const float* points, int count, const SkPa
///////////////////////////////////////////////////////////////////////////////
bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, float threshold,
- std::vector<Vertex>& outputVertices) {
+ std::vector<Vertex>& outputVertices) {
PathApproximationInfo approximationInfo(1.0f, 1.0f, threshold);
return approximatePathOutlineVertices(path, true, approximationInfo, outputVertices);
}
@@ -932,6 +892,7 @@ public:
}
}
}
+
private:
bool initialized = false;
double lastX = 0;
@@ -940,7 +901,8 @@ private:
};
bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool forceClose,
- const PathApproximationInfo& approximationInfo, std::vector<Vertex>& outputVertices) {
+ const PathApproximationInfo& approximationInfo,
+ std::vector<Vertex>& outputVertices) {
ATRACE_CALL();
// TODO: to support joins other than sharp miter, join vertices should be labelled in the
@@ -950,7 +912,7 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
SkPath::Verb v;
ClockwiseEnforcer clockwiseEnforcer;
while (SkPath::kDone_Verb != (v = iter.next(pts))) {
- switch (v) {
+ switch (v) {
case SkPath::kMove_Verb:
outputVertices.push_back(Vertex{pts[0].x(), pts[0].y()});
ALOGV("Move to pos %f %f", pts[0].x(), pts[0].y());
@@ -967,22 +929,17 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
break;
case SkPath::kQuad_Verb:
ALOGV("kQuad_Verb");
- recursiveQuadraticBezierVertices(
- pts[0].x(), pts[0].y(),
- pts[2].x(), pts[2].y(),
- pts[1].x(), pts[1].y(),
- approximationInfo, outputVertices);
+ recursiveQuadraticBezierVertices(pts[0].x(), pts[0].y(), pts[2].x(), pts[2].y(),
+ pts[1].x(), pts[1].y(), approximationInfo,
+ outputVertices);
clockwiseEnforcer.addPoint(pts[1]);
clockwiseEnforcer.addPoint(pts[2]);
break;
case SkPath::kCubic_Verb:
ALOGV("kCubic_Verb");
- recursiveCubicBezierVertices(
- pts[0].x(), pts[0].y(),
- pts[1].x(), pts[1].y(),
- pts[3].x(), pts[3].y(),
- pts[2].x(), pts[2].y(),
- approximationInfo, outputVertices);
+ recursiveCubicBezierVertices(pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y(),
+ pts[3].x(), pts[3].y(), pts[2].x(), pts[2].y(),
+ approximationInfo, outputVertices);
clockwiseEnforcer.addPoint(pts[1]);
clockwiseEnforcer.addPoint(pts[2]);
clockwiseEnforcer.addPoint(pts[3]);
@@ -990,37 +947,33 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
case SkPath::kConic_Verb: {
ALOGV("kConic_Verb");
SkAutoConicToQuads converter;
- const SkPoint* quads = converter.computeQuads(pts, iter.conicWeight(),
- approximationInfo.thresholdForConicQuads);
+ const SkPoint* quads = converter.computeQuads(
+ pts, iter.conicWeight(), approximationInfo.thresholdForConicQuads);
for (int i = 0; i < converter.countQuads(); ++i) {
const int offset = 2 * i;
- recursiveQuadraticBezierVertices(
- quads[offset].x(), quads[offset].y(),
- quads[offset+2].x(), quads[offset+2].y(),
- quads[offset+1].x(), quads[offset+1].y(),
- approximationInfo, outputVertices);
+ recursiveQuadraticBezierVertices(quads[offset].x(), quads[offset].y(),
+ quads[offset + 2].x(), quads[offset + 2].y(),
+ quads[offset + 1].x(), quads[offset + 1].y(),
+ approximationInfo, outputVertices);
}
clockwiseEnforcer.addPoint(pts[1]);
clockwiseEnforcer.addPoint(pts[2]);
break;
}
default:
- static_assert(SkPath::kMove_Verb == 0
- && SkPath::kLine_Verb == 1
- && SkPath::kQuad_Verb == 2
- && SkPath::kConic_Verb == 3
- && SkPath::kCubic_Verb == 4
- && SkPath::kClose_Verb == 5
- && SkPath::kDone_Verb == 6,
- "Path enum changed, new types may have been added");
+ static_assert(SkPath::kMove_Verb == 0 && SkPath::kLine_Verb == 1 &&
+ SkPath::kQuad_Verb == 2 && SkPath::kConic_Verb == 3 &&
+ SkPath::kCubic_Verb == 4 && SkPath::kClose_Verb == 5 &&
+ SkPath::kDone_Verb == 6,
+ "Path enum changed, new types may have been added");
break;
- }
+ }
}
bool wasClosed = false;
int size = outputVertices.size();
if (size >= 2 && outputVertices[0].x == outputVertices[size - 1].x &&
- outputVertices[0].y == outputVertices[size - 1].y) {
+ outputVertices[0].y == outputVertices[size - 1].y) {
outputVertices.pop_back();
wasClosed = true;
}
@@ -1045,19 +998,17 @@ static inline float getThreshold(const PathApproximationInfo& info, float dx, fl
return info.thresholdSquared * scale;
}
-void PathTessellator::recursiveCubicBezierVertices(
- float p1x, float p1y, float c1x, float c1y,
- float p2x, float p2y, float c2x, float c2y,
- const PathApproximationInfo& approximationInfo,
- std::vector<Vertex>& outputVertices, int depth) {
+void PathTessellator::recursiveCubicBezierVertices(float p1x, float p1y, float c1x, float c1y,
+ float p2x, float p2y, float c2x, float c2y,
+ const PathApproximationInfo& approximationInfo,
+ std::vector<Vertex>& outputVertices, int depth) {
float dx = p2x - p1x;
float dy = p2y - p1y;
float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx);
float d2 = fabs((c2x - p2x) * dy - (c2y - p2y) * dx);
float d = d1 + d2;
- if (depth >= MAX_DEPTH
- || d * d <= getThreshold(approximationInfo, dx, dy)) {
+ if (depth >= MAX_DEPTH || d * d <= getThreshold(approximationInfo, dx, dy)) {
// below thresh, draw line by adding endpoint
outputVertices.push_back(Vertex{p2x, p2y});
} else {
@@ -1078,30 +1029,23 @@ void PathTessellator::recursiveCubicBezierVertices(
float mx = (p1c1c2x + p2c1c2x) * 0.5f;
float my = (p1c1c2y + p2c1c2y) * 0.5f;
- recursiveCubicBezierVertices(
- p1x, p1y, p1c1x, p1c1y,
- mx, my, p1c1c2x, p1c1c2y,
- approximationInfo, outputVertices, depth + 1);
- recursiveCubicBezierVertices(
- mx, my, p2c1c2x, p2c1c2y,
- p2x, p2y, p2c2x, p2c2y,
- approximationInfo, outputVertices, depth + 1);
+ recursiveCubicBezierVertices(p1x, p1y, p1c1x, p1c1y, mx, my, p1c1c2x, p1c1c2y,
+ approximationInfo, outputVertices, depth + 1);
+ recursiveCubicBezierVertices(mx, my, p2c1c2x, p2c1c2y, p2x, p2y, p2c2x, p2c2y,
+ approximationInfo, outputVertices, depth + 1);
}
}
void PathTessellator::recursiveQuadraticBezierVertices(
- float ax, float ay,
- float bx, float by,
- float cx, float cy,
- const PathApproximationInfo& approximationInfo,
- std::vector<Vertex>& outputVertices, int depth) {
+ float ax, float ay, float bx, float by, float cx, float cy,
+ const PathApproximationInfo& approximationInfo, std::vector<Vertex>& outputVertices,
+ int depth) {
float dx = bx - ax;
float dy = by - ay;
// d is the cross product of vector (B-A) and (C-B).
float d = (cx - bx) * dy - (cy - by) * dx;
- if (depth >= MAX_DEPTH
- || d * d <= getThreshold(approximationInfo, dx, dy)) {
+ if (depth >= MAX_DEPTH || d * d <= getThreshold(approximationInfo, dx, dy)) {
// below thresh, draw line by adding endpoint
outputVertices.push_back(Vertex{bx, by});
} else {
@@ -1114,12 +1058,12 @@ void PathTessellator::recursiveQuadraticBezierVertices(
float mx = (acx + bcx) * 0.5f;
float my = (acy + bcy) * 0.5f;
- recursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy,
- approximationInfo, outputVertices, depth + 1);
- recursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy,
- approximationInfo, outputVertices, depth + 1);
+ recursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy, approximationInfo,
+ outputVertices, depth + 1);
+ recursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy, approximationInfo,
+ outputVertices, depth + 1);
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/PathTessellator.h b/libs/hwui/PathTessellator.h
index cddfb049212c..ed268324b341 100644
--- a/libs/hwui/PathTessellator.h
+++ b/libs/hwui/PathTessellator.h
@@ -39,11 +39,10 @@ namespace uirenderer {
*/
struct PathApproximationInfo {
PathApproximationInfo(float invScaleX, float invScaleY, float pixelThreshold)
- : thresholdSquared(pixelThreshold * pixelThreshold)
- , sqrInvScaleX(invScaleX * invScaleX)
- , sqrInvScaleY(invScaleY * invScaleY)
- , thresholdForConicQuads(pixelThreshold * std::min(invScaleX, invScaleY) / 2.0f) {
- };
+ : thresholdSquared(pixelThreshold * pixelThreshold)
+ , sqrInvScaleX(invScaleX * invScaleX)
+ , sqrInvScaleY(invScaleY * invScaleY)
+ , thresholdForConicQuads(pixelThreshold * std::min(invScaleX, invScaleY) / 2.0f){};
const float thresholdSquared;
const float sqrInvScaleX;
@@ -64,7 +63,8 @@ public:
static void extractTessellationScales(const Matrix4& transform, float* scaleX, float* scaleY);
/**
- * Populates a VertexBuffer with a tessellated approximation of the input convex path, as a single
+ * Populates a VertexBuffer with a tessellated approximation of the input convex path, as a
+ * single
* triangle strip. Note: joins are not currently supported.
*
* @param path The path to be approximated
@@ -74,8 +74,8 @@ public:
* vertex approximation, and correct AA ramp offsetting.
* @param vertexBuffer The output buffer
*/
- static void tessellatePath(const SkPath& path, const SkPaint* paint,
- const mat4& transform, VertexBuffer& vertexBuffer);
+ static void tessellatePath(const SkPath& path, const SkPaint* paint, const mat4& transform,
+ VertexBuffer& vertexBuffer);
/**
* Populates a VertexBuffer with a tessellated approximation of points as a single triangle
@@ -84,12 +84,13 @@ public:
* @param points The center vertices of the points to be drawn
* @param count The number of floats making up the point vertices
* @param paint The paint the points will be drawn with indicating AA, stroke width & cap
- * @param transform The transform the points will be drawn with, used to drive stretch-aware path
+ * @param transform The transform the points will be drawn with, used to drive stretch-aware
+ * path
* vertex approximation, and correct AA ramp offsetting
* @param vertexBuffer The output buffer
*/
static void tessellatePoints(const float* points, int count, const SkPaint* paint,
- const mat4& transform, VertexBuffer& vertexBuffer);
+ const mat4& transform, VertexBuffer& vertexBuffer);
/**
* Populates a VertexBuffer with a tessellated approximation of lines as a single triangle
@@ -98,12 +99,13 @@ public:
* @param points Pairs of endpoints defining the lines to be drawn
* @param count The number of floats making up the line vertices
* @param paint The paint the lines will be drawn with indicating AA, stroke width & cap
- * @param transform The transform the points will be drawn with, used to drive stretch-aware path
+ * @param transform The transform the points will be drawn with, used to drive stretch-aware
+ * path
* vertex approximation, and correct AA ramp offsetting
* @param vertexBuffer The output buffer
*/
static void tessellateLines(const float* points, int count, const SkPaint* paint,
- const mat4& transform, VertexBuffer& vertexBuffer);
+ const mat4& transform, VertexBuffer& vertexBuffer);
/**
* Approximates a convex outline into a clockwise Vector of 2d vertices.
@@ -112,38 +114,35 @@ public:
* @param threshold The threshold of acceptable error (in pixels) when approximating
* @param outputVertices An empty Vector which will be populated with the output
*/
- static bool approximatePathOutlineVertices(const SkPath &path, float threshold,
- std::vector<Vertex> &outputVertices);
+ static bool approximatePathOutlineVertices(const SkPath& path, float threshold,
+ std::vector<Vertex>& outputVertices);
private:
- static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
- const PathApproximationInfo& approximationInfo, std::vector<Vertex> &outputVertices);
+ static bool approximatePathOutlineVertices(const SkPath& path, bool forceClose,
+ const PathApproximationInfo& approximationInfo,
+ std::vector<Vertex>& outputVertices);
-/*
- endpoints a & b,
- control c
- */
- static void recursiveQuadraticBezierVertices(
- float ax, float ay,
- float bx, float by,
- float cx, float cy,
- const PathApproximationInfo& approximationInfo,
- std::vector<Vertex> &outputVertices, int depth = 0);
-
-/*
- endpoints p1, p2
- control c1, c2
- */
- static void recursiveCubicBezierVertices(
- float p1x, float p1y,
- float c1x, float c1y,
- float p2x, float p2y,
- float c2x, float c2y,
- const PathApproximationInfo& approximationInfo,
- std::vector<Vertex> &outputVertices, int depth = 0);
+ /*
+ endpoints a & b,
+ control c
+ */
+ static void recursiveQuadraticBezierVertices(float ax, float ay, float bx, float by, float cx,
+ float cy,
+ const PathApproximationInfo& approximationInfo,
+ std::vector<Vertex>& outputVertices,
+ int depth = 0);
+
+ /*
+ endpoints p1, p2
+ control c1, c2
+ */
+ static void recursiveCubicBezierVertices(float p1x, float p1y, float c1x, float c1y, float p2x,
+ float p2y, float c2x, float c2y,
+ const PathApproximationInfo& approximationInfo,
+ std::vector<Vertex>& outputVertices, int depth = 0);
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_PATH_TESSELLATOR_H
+#endif // ANDROID_HWUI_PATH_TESSELLATOR_H
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index 2a96b6914afc..910a9889db1f 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -31,7 +31,7 @@ namespace uirenderer {
// CPU pixel buffer
///////////////////////////////////////////////////////////////////////////////
-class CpuPixelBuffer: public PixelBuffer {
+class CpuPixelBuffer : public PixelBuffer {
public:
CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
@@ -48,8 +48,7 @@ private:
CpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
: PixelBuffer(format, width, height)
- , mBuffer(new uint8_t[width * height * formatSize(format)]) {
-}
+ , mBuffer(new uint8_t[width * height * formatSize(format)]) {}
uint8_t* CpuPixelBuffer::map(AccessMode mode) {
if (mAccessMode == kAccessMode_None) {
@@ -63,15 +62,15 @@ void CpuPixelBuffer::unmap() {
}
void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
- mFormat, GL_UNSIGNED_BYTE, &mBuffer[offset]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
+ &mBuffer[offset]);
}
///////////////////////////////////////////////////////////////////////////////
// GPU pixel buffer
///////////////////////////////////////////////////////////////////////////////
-class GpuPixelBuffer: public PixelBuffer {
+class GpuPixelBuffer : public PixelBuffer {
public:
GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
~GpuPixelBuffer();
@@ -89,11 +88,10 @@ private:
Caches& mCaches;
};
-GpuPixelBuffer::GpuPixelBuffer(GLenum format,
- uint32_t width, uint32_t height)
+GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
: PixelBuffer(format, width, height)
, mMappedPointer(nullptr)
- , mCaches(Caches::getInstance()){
+ , mCaches(Caches::getInstance()) {
glGenBuffers(1, &mBuffer);
mCaches.pixelBufferState().bind(mBuffer);
@@ -108,7 +106,7 @@ GpuPixelBuffer::~GpuPixelBuffer() {
uint8_t* GpuPixelBuffer::map(AccessMode mode) {
if (mAccessMode == kAccessMode_None) {
mCaches.pixelBufferState().bind(mBuffer);
- mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
+ mMappedPointer = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
if (CC_UNLIKELY(!mMappedPointer)) {
GLUtils::dumpGLErrors();
LOG_ALWAYS_FATAL("Failed to map PBO");
@@ -138,8 +136,8 @@ void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t hei
// If the buffer is not mapped, unmap() will not bind it
mCaches.pixelBufferState().bind(mBuffer);
unmap();
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
- GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
+ reinterpret_cast<void*>(offset));
mCaches.pixelBufferState().unbind();
}
@@ -147,13 +145,12 @@ void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t hei
// Factory
///////////////////////////////////////////////////////////////////////////////
-PixelBuffer* PixelBuffer::create(GLenum format,
- uint32_t width, uint32_t height, BufferType type) {
+PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
return new GpuPixelBuffer(format, width, height);
}
return new CpuPixelBuffer(format, width, height);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
index 77d5e413cb36..e7e341b90ad3 100644
--- a/libs/hwui/PixelBuffer.h
+++ b/libs/hwui/PixelBuffer.h
@@ -45,10 +45,7 @@ namespace uirenderer {
*/
class PixelBuffer {
public:
- enum BufferType {
- kBufferType_Auto,
- kBufferType_CPU
- };
+ enum BufferType { kBufferType_Auto, kBufferType_CPU };
enum AccessMode {
kAccessMode_None = 0,
@@ -66,17 +63,14 @@ public:
* a CPU or GPU buffer.
*/
static PixelBuffer* create(GLenum format, uint32_t width, uint32_t height,
- BufferType type = kBufferType_Auto);
+ BufferType type = kBufferType_Auto);
- virtual ~PixelBuffer() {
- }
+ virtual ~PixelBuffer() {}
/**
* Returns the format of this render buffer.
*/
- GLenum getFormat() const {
- return mFormat;
- }
+ GLenum getFormat() const { return mFormat; }
/**
* Maps this before with the specified access mode. This method
@@ -95,9 +89,7 @@ public:
* Returns the current access mode for this buffer. If the buffer
* is not mapped, this method returns kAccessMode_None.
*/
- AccessMode getAccessMode() const {
- return mAccessMode;
- }
+ AccessMode getAccessMode() const { return mAccessMode; }
/**
* Upload the specified rectangle of this pixel buffer as a
@@ -121,23 +113,17 @@ public:
/**
* Returns the width of the render buffer in pixels.
*/
- uint32_t getWidth() const {
- return mWidth;
- }
+ uint32_t getWidth() const { return mWidth; }
/**
* Returns the height of the render buffer in pixels.
*/
- uint32_t getHeight() const {
- return mHeight;
- }
+ uint32_t getHeight() const { return mHeight; }
/**
* Returns the size of this pixel buffer in bytes.
*/
- uint32_t getSize() const {
- return mWidth * mHeight * formatSize(mFormat);
- }
+ uint32_t getSize() const { return mWidth * mHeight * formatSize(mFormat); }
/**
* Returns the offset of a pixel in this pixel buffer, in bytes.
@@ -178,7 +164,7 @@ public:
return 3;
}
- ALOGE("unsupported format: %d",format);
+ ALOGE("unsupported format: %d", format);
return 0;
}
@@ -187,9 +173,8 @@ protected:
* Creates a new render buffer in the specified format and dimensions.
* The format must be GL_ALPHA or GL_RGBA.
*/
- PixelBuffer(GLenum format, uint32_t width, uint32_t height):
- mFormat(format), mWidth(width), mHeight(height), mAccessMode(kAccessMode_None) {
- }
+ PixelBuffer(GLenum format, uint32_t width, uint32_t height)
+ : mFormat(format), mWidth(width), mHeight(height), mAccessMode(kAccessMode_None) {}
/**
* Unmaps this buffer, if needed. After the buffer is unmapped,
@@ -205,9 +190,9 @@ protected:
AccessMode mAccessMode;
-}; // class PixelBuffer
+}; // class PixelBuffer
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_PIXEL_BUFFER_H
+#endif // ANDROID_HWUI_PIXEL_BUFFER_H
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index a295c5debc67..16966619aace 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -22,12 +22,8 @@ namespace android {
namespace uirenderer {
static const char* JANK_TYPE_NAMES[] = {
- "Missed Vsync",
- "High input latency",
- "Slow UI thread",
- "Slow bitmap uploads",
- "Slow issue draw commands",
-};
+ "Missed Vsync", "High input latency", "Slow UI thread",
+ "Slow bitmap uploads", "Slow issue draw commands", "Frame deadline missed"};
// The bucketing algorithm controls so to speak
// If a frame is <= to this it goes in bucket 0
@@ -54,10 +50,8 @@ static uint32_t frameCountIndexForFrameTime(nsecs_t frameTime) {
// index = threshold + (amountAboveThreshold / 2)
// However if index is <= this will do nothing. It will underflow, do
// a right shift by 0 (no-op), then overflow back to the original value
- index = ((index - kBucket4msIntervals) >> (index > kBucket4msIntervals))
- + kBucket4msIntervals;
- index = ((index - kBucket2msIntervals) >> (index > kBucket2msIntervals))
- + kBucket2msIntervals;
+ index = ((index - kBucket4msIntervals) >> (index > kBucket4msIntervals)) + kBucket4msIntervals;
+ index = ((index - kBucket2msIntervals) >> (index > kBucket2msIntervals)) + kBucket2msIntervals;
// If index was < minThreshold at the start of all this it's going to
// be a pretty garbage value right now. However, mask is 0 so we'll end
// up with the desired result of 0.
@@ -101,8 +95,7 @@ void ProfileData::mergeWith(const ProfileData& other) {
mJankFrameCount += other.mJankFrameCount;
mTotalFrameCount >>= divider;
mTotalFrameCount += other.mTotalFrameCount;
- if (mStatStartTime > other.mStatStartTime
- || mStatStartTime == 0) {
+ if (mStatStartTime > other.mStatStartTime || mStatStartTime == 0) {
mStatStartTime = other.mStatStartTime;
}
}
@@ -111,7 +104,8 @@ void ProfileData::dump(int fd) const {
dprintf(fd, "\nStats since: %" PRIu64 "ns", mStatStartTime);
dprintf(fd, "\nTotal frames rendered: %u", mTotalFrameCount);
dprintf(fd, "\nJanky frames: %u (%.2f%%)", mJankFrameCount,
- (float) mJankFrameCount / (float) mTotalFrameCount * 100.0f);
+ mTotalFrameCount == 0 ? 0.0f :
+ (float)mJankFrameCount / (float)mTotalFrameCount * 100.0f);
dprintf(fd, "\n50th percentile: %ums", findPercentile(50));
dprintf(fd, "\n90th percentile: %ums", findPercentile(90));
dprintf(fd, "\n95th percentile: %ums", findPercentile(95));
diff --git a/libs/hwui/ProfileData.h b/libs/hwui/ProfileData.h
index d53ee29511f0..564920b60328 100644
--- a/libs/hwui/ProfileData.h
+++ b/libs/hwui/ProfileData.h
@@ -33,6 +33,7 @@ enum JankType {
kSlowUI,
kSlowSync,
kSlowRT,
+ kMissedDeadline,
// must be last
NUM_BUCKETS,
@@ -70,8 +71,8 @@ public:
void histogramForEach(const std::function<void(HistogramEntry)>& callback) const;
constexpr static int HistogramSize() {
- return std::tuple_size<decltype(ProfileData::mFrameCounts)>::value
- + std::tuple_size<decltype(ProfileData::mSlowFrameCounts)>::value;
+ return std::tuple_size<decltype(ProfileData::mFrameCounts)>::value +
+ std::tuple_size<decltype(ProfileData::mSlowFrameCounts)>::value;
}
// Visible for testing
@@ -82,7 +83,7 @@ private:
// Open our guts up to unit tests
friend class MockProfileData;
- std::array <uint32_t, NUM_BUCKETS> mJankTypeCounts;
+ std::array<uint32_t, NUM_BUCKETS> mJankTypeCounts;
// See comments on kBucket* constants for what this holds
std::array<uint32_t, 57> mFrameCounts;
// Holds a histogram of frame times in 50ms increments from 150ms to 5s
@@ -106,4 +107,3 @@ public:
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/ProfileDataContainer.cpp b/libs/hwui/ProfileDataContainer.cpp
index 9db0ef1d6e9a..38e0f0aa8d83 100644
--- a/libs/hwui/ProfileDataContainer.cpp
+++ b/libs/hwui/ProfileDataContainer.cpp
@@ -16,8 +16,10 @@
#include "ProfileDataContainer.h"
-#include <log/log.h>
+#include <errno.h>
+
#include <cutils/ashmem.h>
+#include <log/log.h>
#include <errno.h>
#include <sys/mman.h>
@@ -51,21 +53,20 @@ void ProfileDataContainer::switchStorageToAshmem(int ashmemfd) {
int regionSize = ashmem_get_size_region(ashmemfd);
if (regionSize < 0) {
int err = errno;
- ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err, strerror(err));
+ ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err,
+ strerror(err));
return;
}
if (regionSize < static_cast<int>(sizeof(ProfileData))) {
- ALOGW("Ashmem region is too small! Received %d, required %u",
- regionSize, static_cast<unsigned int>(sizeof(ProfileData)));
+ ALOGW("Ashmem region is too small! Received %d, required %u", regionSize,
+ static_cast<unsigned int>(sizeof(ProfileData)));
return;
}
ProfileData* newData = reinterpret_cast<ProfileData*>(
- mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE,
- MAP_SHARED, ashmemfd, 0));
+ mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE, MAP_SHARED, ashmemfd, 0));
if (newData == MAP_FAILED) {
int err = errno;
- ALOGW("Failed to move profile data to ashmem fd %d, error = %d",
- ashmemfd, err);
+ ALOGW("Failed to move profile data to ashmem fd %d, error = %d", ashmemfd, err);
return;
}
diff --git a/libs/hwui/ProfileDataContainer.h b/libs/hwui/ProfileDataContainer.h
index d2de24188c7c..a39869491ede 100644
--- a/libs/hwui/ProfileDataContainer.h
+++ b/libs/hwui/ProfileDataContainer.h
@@ -24,6 +24,7 @@ namespace uirenderer {
class ProfileDataContainer {
PREVENT_COPY_AND_ASSIGN(ProfileDataContainer);
+
public:
explicit ProfileDataContainer() {}
diff --git a/libs/hwui/ProfileRenderer.cpp b/libs/hwui/ProfileRenderer.cpp
index 0ad484ce0687..8a00ffa54c58 100644
--- a/libs/hwui/ProfileRenderer.cpp
+++ b/libs/hwui/ProfileRenderer.cpp
@@ -20,7 +20,7 @@ namespace android {
namespace uirenderer {
void ProfileRenderer::drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) {
+ const SkPaint& paint) {
mRenderer.drawRect(left, top, right, bottom, &paint);
}
diff --git a/libs/hwui/ProfileRenderer.h b/libs/hwui/ProfileRenderer.h
index b9e586f592e8..5c8bb2529fb4 100644
--- a/libs/hwui/ProfileRenderer.h
+++ b/libs/hwui/ProfileRenderer.h
@@ -23,9 +23,7 @@ namespace uirenderer {
class ProfileRenderer : public IProfileRenderer {
public:
- ProfileRenderer(BakedOpRenderer& renderer)
- : mRenderer(renderer) {
- }
+ ProfileRenderer(BakedOpRenderer& renderer) : mRenderer(renderer) {}
void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
void drawRects(const float* rects, int count, const SkPaint& paint) override;
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index e43b80d440e7..052798b9cea9 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -151,7 +151,7 @@ GLuint Program::buildShader(const char* source, GLenum type) {
}
void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
- const mat4& transformMatrix, bool offset) {
+ const mat4& transformMatrix, bool offset) {
if (projectionMatrix != mProjection || offset != mOffset) {
if (CC_LIKELY(!offset)) {
glUniformMatrix4fv(projection, 1, GL_FALSE, &projectionMatrix.data[0]);
@@ -195,5 +195,5 @@ void Program::remove() {
mUse = false;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 2becfcb709c3..dcc2bd410ebd 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -39,25 +39,25 @@ namespace uirenderer {
// Debug
#if DEBUG_PROGRAMS
- #define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__)
+#define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define PROGRAM_LOGD(...)
+#define PROGRAM_LOGD(...)
#endif
#define COLOR_COMPONENT_THRESHOLD 1.0f
#define COLOR_COMPONENT_INV_THRESHOLD 0.0f
-#define PROGRAM_KEY_TEXTURE 0x01
-#define PROGRAM_KEY_A8_TEXTURE 0x02
-#define PROGRAM_KEY_BITMAP 0x04
-#define PROGRAM_KEY_GRADIENT 0x08
-#define PROGRAM_KEY_BITMAP_FIRST 0x10
-#define PROGRAM_KEY_COLOR_MATRIX 0x20
-#define PROGRAM_KEY_COLOR_BLEND 0x40
-#define PROGRAM_KEY_BITMAP_NPOT 0x80
-#define PROGRAM_KEY_BITMAP_EXTERNAL 0x100
-
-#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
+#define PROGRAM_KEY_TEXTURE 0x01
+#define PROGRAM_KEY_A8_TEXTURE 0x02
+#define PROGRAM_KEY_BITMAP 0x04
+#define PROGRAM_KEY_GRADIENT 0x08
+#define PROGRAM_KEY_BITMAP_FIRST 0x10
+#define PROGRAM_KEY_COLOR_MATRIX 0x20
+#define PROGRAM_KEY_COLOR_BLEND 0x40
+#define PROGRAM_KEY_BITMAP_NPOT 0x80
+#define PROGRAM_KEY_BITMAP_EXTERNAL 0x100
+
+#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
#define PROGRAM_KEY_SWAP_SRC_DST_SHIFT 13
@@ -71,7 +71,7 @@ namespace uirenderer {
#define PROGRAM_BITMAP_WRAPS_SHIFT 9
#define PROGRAM_BITMAP_WRAPT_SHIFT 11
-#define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type
+#define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type
#define PROGRAM_MODULATE_SHIFT 35
#define PROGRAM_HAS_VERTEX_ALPHA_SHIFT 36
@@ -91,7 +91,7 @@ namespace uirenderer {
#define PROGRAM_HAS_LINEAR_TEXTURE 45
#define PROGRAM_HAS_COLOR_SPACE_CONVERSION 46
-#define PROGRAM_TRANSFER_FUNCTION 47 // 2 bits for transfer function
+#define PROGRAM_TRANSFER_FUNCTION 47 // 2 bits for transfer function
#define PROGRAM_HAS_TRANSLUCENT_CONVERSION 49
///////////////////////////////////////////////////////////////////////////////
@@ -110,21 +110,11 @@ typedef uint64_t programid;
* A ProgramDescription must be used in conjunction with a ProgramCache.
*/
struct ProgramDescription {
- enum class ColorFilterMode : int8_t {
- None = 0,
- Matrix,
- Blend
- };
-
- enum Gradient : int8_t {
- kGradientLinear = 0,
- kGradientCircular,
- kGradientSweep
- };
-
- ProgramDescription() {
- reset();
- }
+ enum class ColorFilterMode : int8_t { None = 0, Matrix, Blend };
+
+ enum Gradient : int8_t { kGradientLinear = 0, kGradientCircular, kGradientSweep };
+
+ ProgramDescription() { reset(); }
// Texturing
bool hasTexture;
@@ -243,7 +233,7 @@ struct ProgramDescription {
*/
bool setAlpha8ColorModulate(const float r, const float g, const float b, const float a) {
modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
- g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
+ g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
return modulate;
}
@@ -277,12 +267,12 @@ struct ProgramDescription {
break;
case ColorFilterMode::Blend:
key |= PROGRAM_KEY_COLOR_BLEND;
- key |= ((int) colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
+ key |= ((int)colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
break;
case ColorFilterMode::None:
break;
}
- key |= ((int) framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
+ key |= ((int)framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
key |= programid(swapSrcDst) << PROGRAM_KEY_SWAP_SRC_DST_SHIFT;
key |= programid(modulate) << PROGRAM_MODULATE_SHIFT;
key |= programid(hasVertexAlpha) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
@@ -307,8 +297,7 @@ struct ProgramDescription {
void log(const char* message) const {
#if DEBUG_PROGRAMS
programid k = key();
- PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
- uint32_t(k & 0xffffffff));
+ PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32), uint32_t(k & 0xffffffff));
#endif
}
@@ -325,7 +314,7 @@ private:
return 0;
}
-}; // struct ProgramDescription
+}; // struct ProgramDescription
/**
* A program holds a vertex and a fragment shader. It offers several utility
@@ -333,10 +322,7 @@ private:
*/
class Program {
public:
- enum ShaderBindings {
- kBindingPosition,
- kBindingTexCoords
- };
+ enum ShaderBindings { kBindingPosition, kBindingTexCoords };
/**
* Creates a new program with the specified vertex and fragment
@@ -370,23 +356,19 @@ public:
* Indicates whether this program is currently in use with
* the GL context.
*/
- inline bool isInUse() const {
- return mUse;
- }
+ inline bool isInUse() const { return mUse; }
/**
* Indicates whether this program was correctly compiled and linked.
*/
- inline bool isInitialized() const {
- return mInitialized;
- }
+ inline bool isInitialized() const { return mInitialized; }
/**
* Binds the program with the specified projection, modelView and
* transform matrices.
*/
- void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
- const mat4& transformMatrix, bool offset = false);
+ void set(const mat4& projectionMatrix, const mat4& modelViewMatrix, const mat4& transformMatrix,
+ bool offset = false);
/**
* Sets the color associated with this shader.
@@ -456,9 +438,9 @@ private:
mat4 mProjection;
bool mOffset;
-}; // class Program
+}; // class Program
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_PROGRAM_H
+#endif // ANDROID_HWUI_PROGRAM_H
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 11360a1f6e33..1164ebfdf1e5 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -41,19 +41,14 @@ namespace uirenderer {
const char* gVS_Header_Start =
"#version 100\n"
"attribute vec4 position;\n";
-const char* gVS_Header_Attributes_TexCoords =
- "attribute vec2 texCoords;\n";
-const char* gVS_Header_Attributes_Colors =
- "attribute vec4 colors;\n";
-const char* gVS_Header_Attributes_VertexAlphaParameters =
- "attribute float vtxAlpha;\n";
-const char* gVS_Header_Uniforms_TextureTransform =
- "uniform mat4 mainTextureTransform;\n";
+const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n";
+const char* gVS_Header_Attributes_Colors = "attribute vec4 colors;\n";
+const char* gVS_Header_Attributes_VertexAlphaParameters = "attribute float vtxAlpha;\n";
+const char* gVS_Header_Uniforms_TextureTransform = "uniform mat4 mainTextureTransform;\n";
const char* gVS_Header_Uniforms =
- "uniform mat4 projection;\n" \
+ "uniform mat4 projection;\n"
"uniform mat4 transform;\n";
-const char* gVS_Header_Uniforms_HasGradient =
- "uniform mat4 screenSpace;\n";
+const char* gVS_Header_Uniforms_HasGradient = "uniform mat4 screenSpace;\n";
const char* gVS_Header_Uniforms_HasBitmap =
"uniform mat4 textureTransform;\n"
"uniform mediump vec2 textureDimension;\n";
@@ -61,35 +56,24 @@ const char* gVS_Header_Uniforms_HasRoundRectClip =
"uniform mat4 roundRectInvTransform;\n"
"uniform mediump vec4 roundRectInnerRectLTWH;\n"
"uniform mediump float roundRectRadius;\n";
-const char* gVS_Header_Varyings_HasTexture =
- "varying highp vec2 outTexCoords;\n";
-const char* gVS_Header_Varyings_HasColors =
- "varying vec4 outColors;\n";
-const char* gVS_Header_Varyings_HasVertexAlpha =
- "varying float alpha;\n";
-const char* gVS_Header_Varyings_HasBitmap =
- "varying highp vec2 outBitmapTexCoords;\n";
+const char* gVS_Header_Varyings_HasTexture = "varying vec2 outTexCoords;\n";
+const char* gVS_Header_Varyings_HasColors = "varying vec4 outColors;\n";
+const char* gVS_Header_Varyings_HasVertexAlpha = "varying float alpha;\n";
+const char* gVS_Header_Varyings_HasBitmap = "varying highp vec2 outBitmapTexCoords;\n";
const char* gVS_Header_Varyings_HasGradient[6] = {
// Linear
- "varying highp vec2 linear;\n",
- "varying float linear;\n",
+ "varying highp vec2 linear;\n", "varying float linear;\n",
// Circular
- "varying highp vec2 circular;\n",
- "varying highp vec2 circular;\n",
+ "varying highp vec2 circular;\n", "varying highp vec2 circular;\n",
// Sweep
- "varying highp vec2 sweep;\n",
- "varying highp vec2 sweep;\n",
+ "varying highp vec2 sweep;\n", "varying highp vec2 sweep;\n",
};
-const char* gVS_Header_Varyings_HasRoundRectClip =
- "varying mediump vec2 roundRectPos;\n";
-const char* gVS_Main =
- "\nvoid main(void) {\n";
-const char* gVS_Main_OutTexCoords =
- " outTexCoords = texCoords;\n";
-const char* gVS_Main_OutColors =
- " outColors = colors;\n";
+const char* gVS_Header_Varyings_HasRoundRectClip = "varying mediump vec2 roundRectPos;\n";
+const char* gVS_Main = "\nvoid main(void) {\n";
+const char* gVS_Main_OutTexCoords = " outTexCoords = texCoords;\n";
+const char* gVS_Main_OutColors = " outColors = colors;\n";
const char* gVS_Main_OutTransformedTexCoords =
" outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
const char* gVS_Main_OutGradient[6] = {
@@ -102,53 +86,42 @@ const char* gVS_Main_OutGradient[6] = {
" circular = (screenSpace * position).xy;\n",
// Sweep
- " sweep = (screenSpace * position).xy;\n",
- " sweep = (screenSpace * position).xy;\n"
-};
+ " sweep = (screenSpace * position).xy;\n", " sweep = (screenSpace * position).xy;\n"};
const char* gVS_Main_OutBitmapTexCoords =
" outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
const char* gVS_Main_Position =
" vec4 transformedPosition = projection * transform * position;\n"
" gl_Position = transformedPosition;\n";
-const char* gVS_Main_VertexAlpha =
- " alpha = vtxAlpha;\n";
+const char* gVS_Main_VertexAlpha = " alpha = vtxAlpha;\n";
const char* gVS_Main_HasRoundRectClip =
- " roundRectPos = ((roundRectInvTransform * transformedPosition).xy / roundRectRadius) - roundRectInnerRectLTWH.xy;\n";
-const char* gVS_Footer =
- "}\n\n";
+ " roundRectPos = ((roundRectInvTransform * transformedPosition).xy / roundRectRadius) - "
+ "roundRectInnerRectLTWH.xy;\n";
+const char* gVS_Footer = "}\n\n";
///////////////////////////////////////////////////////////////////////////////
// Fragment shaders snippets
///////////////////////////////////////////////////////////////////////////////
-const char* gFS_Header_Start =
- "#version 100\n";
+const char* gFS_Header_Start = "#version 100\n";
const char* gFS_Header_Extension_FramebufferFetch =
"#extension GL_NV_shader_framebuffer_fetch : enable\n\n";
const char* gFS_Header_Extension_ExternalTexture =
"#extension GL_OES_EGL_image_external : require\n\n";
-const char* gFS_Header =
- "precision mediump float;\n\n";
-const char* gFS_Uniforms_Color =
- "uniform vec4 color;\n";
-const char* gFS_Uniforms_TextureSampler =
- "uniform sampler2D baseSampler;\n";
-const char* gFS_Uniforms_ExternalTextureSampler =
- "uniform samplerExternalOES baseSampler;\n";
+const char* gFS_Header = "precision mediump float;\n\n";
+const char* gFS_Uniforms_Color = "uniform vec4 color;\n";
+const char* gFS_Uniforms_TextureSampler = "uniform sampler2D baseSampler;\n";
+const char* gFS_Uniforms_ExternalTextureSampler = "uniform samplerExternalOES baseSampler;\n";
const char* gFS_Uniforms_GradientSampler[2] = {
"uniform vec2 screenSize;\n"
"uniform sampler2D gradientSampler;\n",
"uniform vec2 screenSize;\n"
"uniform vec4 startColor;\n"
- "uniform vec4 endColor;\n"
-};
-const char* gFS_Uniforms_BitmapSampler =
- "uniform sampler2D bitmapSampler;\n";
-const char* gFS_Uniforms_BitmapExternalSampler =
- "uniform samplerExternalOES bitmapSampler;\n";
+ "uniform vec4 endColor;\n"};
+const char* gFS_Uniforms_BitmapSampler = "uniform sampler2D bitmapSampler;\n";
+const char* gFS_Uniforms_BitmapExternalSampler = "uniform samplerExternalOES bitmapSampler;\n";
const char* gFS_Uniforms_ColorOp[3] = {
// None
"",
@@ -156,8 +129,7 @@ const char* gFS_Uniforms_ColorOp[3] = {
"uniform mat4 colorMatrix;\n"
"uniform vec4 colorMatrixVector;\n",
// PorterDuff
- "uniform vec4 colorBlend;\n"
-};
+ "uniform vec4 colorBlend;\n"};
const char* gFS_Uniforms_HasRoundRectClip =
"uniform mediump vec4 roundRectInnerRectLTWH;\n"
@@ -172,11 +144,8 @@ const char* gFS_Uniforms_TransferFunction[4] = {
// In this order: g, a, b, c, d, e, f
// See ColorSpace::TransferParameters
// We'll use hardware sRGB conversion as much as possible
- "",
- "uniform float transferFunction[7];\n",
- "uniform float transferFunction[5];\n",
- "uniform float transferFunctionGamma;\n"
-};
+ "", "uniform float transferFunction[7];\n", "uniform float transferFunction[5];\n",
+ "uniform float transferFunctionGamma;\n"};
const char* gFS_OETF[2] = {
R"__SHADER__(
@@ -189,8 +158,7 @@ const char* gFS_OETF[2] = {
vec4 OETF(const vec4 linear) {
return vec4(sign(linear.rgb) * OETF_sRGB(abs(linear.rgb)), linear.a);
}
- )__SHADER__"
-};
+ )__SHADER__"};
const char* gFS_ColorConvert[3] = {
// Just OETF
@@ -274,8 +242,7 @@ const char* gFS_TransferFunction[4] = {
pow(x.g, transferFunctionGamma),
pow(x.b, transferFunctionGamma));
}
- )__SHADER__"
-};
+ )__SHADER__"};
// Dithering must be done in the quantization space
// When we are writing to an sRGB framebuffer, we must do the following:
@@ -327,16 +294,12 @@ const char* gFS_Main =
"\nvoid main(void) {\n"
" vec4 fragColor;\n";
-const char* gFS_Main_AddDither =
- " fragColor = dither(fragColor);\n";
+const char* gFS_Main_AddDither = " fragColor = dither(fragColor);\n";
// General case
-const char* gFS_Main_FetchColor =
- " fragColor = color;\n";
-const char* gFS_Main_ModulateColor =
- " fragColor *= color.a;\n";
-const char* gFS_Main_ApplyVertexAlphaLinearInterp =
- " fragColor *= alpha;\n";
+const char* gFS_Main_FetchColor = " fragColor = color;\n";
+const char* gFS_Main_ModulateColor = " fragColor *= color.a;\n";
+const char* gFS_Main_ApplyVertexAlphaLinearInterp = " fragColor *= alpha;\n";
const char* gFS_Main_ApplyVertexAlphaShadowInterp =
// map alpha through shadow alpha sampler
" fragColor *= texture2D(baseSampler, vec2(alpha, 0.5)).a;\n";
@@ -344,8 +307,7 @@ const char* gFS_Main_FetchTexture[2] = {
// Don't modulate
" fragColor = colorConvert(texture2D(baseSampler, outTexCoords));\n",
// Modulate
- " fragColor = color * colorConvert(texture2D(baseSampler, outTexCoords));\n"
-};
+ " fragColor = color * colorConvert(texture2D(baseSampler, outTexCoords));\n"};
const char* gFS_Main_FetchA8Texture[4] = {
// Don't modulate
" fragColor = texture2D(baseSampler, outTexCoords);\n",
@@ -370,53 +332,46 @@ const char* gFS_Main_FetchGradient[6] = {
" vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
" highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
- " vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
-};
+ " vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, "
+ "1.0));\n"};
const char* gFS_Main_FetchBitmap =
" vec4 bitmapColor = colorConvert(texture2D(bitmapSampler, outBitmapTexCoords));\n";
const char* gFS_Main_FetchBitmapNpot =
- " vec4 bitmapColor = colorConvert(texture2D(bitmapSampler, wrap(outBitmapTexCoords)));\n";
-const char* gFS_Main_BlendShadersBG =
- " fragColor = blendShaders(gradientColor, bitmapColor)";
-const char* gFS_Main_BlendShadersGB =
- " fragColor = blendShaders(bitmapColor, gradientColor)";
+ " vec4 bitmapColor = colorConvert(texture2D(bitmapSampler, "
+ "wrap(outBitmapTexCoords)));\n";
+const char* gFS_Main_BlendShadersBG = " fragColor = blendShaders(gradientColor, bitmapColor)";
+const char* gFS_Main_BlendShadersGB = " fragColor = blendShaders(bitmapColor, gradientColor)";
const char* gFS_Main_BlendShaders_Modulate[6] = {
// Don't modulate
- ";\n",
- ";\n",
+ ";\n", ";\n",
// Modulate
- " * color.a;\n",
- " * color.a;\n",
+ " * color.a;\n", " * color.a;\n",
// Modulate with alpha 8 texture
" * texture2D(baseSampler, outTexCoords).a;\n",
" * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n",
};
const char* gFS_Main_GradientShader_Modulate[6] = {
// Don't modulate
- " fragColor = gradientColor;\n",
- " fragColor = gradientColor;\n",
+ " fragColor = gradientColor;\n", " fragColor = gradientColor;\n",
// Modulate
- " fragColor = gradientColor * color.a;\n",
- " fragColor = gradientColor * color.a;\n",
+ " fragColor = gradientColor * color.a;\n", " fragColor = gradientColor * color.a;\n",
// Modulate with alpha 8 texture
" fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = gradientColor * gamma(texture2D(baseSampler, outTexCoords).a, gradientColor.rgb);\n",
- };
+ " fragColor = gradientColor * gamma(texture2D(baseSampler, outTexCoords).a, "
+ "gradientColor.rgb);\n",
+};
const char* gFS_Main_BitmapShader_Modulate[6] = {
// Don't modulate
- " fragColor = bitmapColor;\n",
- " fragColor = bitmapColor;\n",
+ " fragColor = bitmapColor;\n", " fragColor = bitmapColor;\n",
// Modulate
- " fragColor = bitmapColor * color.a;\n",
- " fragColor = bitmapColor * color.a;\n",
+ " fragColor = bitmapColor * color.a;\n", " fragColor = bitmapColor * color.a;\n",
// Modulate with alpha 8 texture
" fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n",
- " fragColor = bitmapColor * gamma(texture2D(baseSampler, outTexCoords).a, bitmapColor.rgb);\n",
- };
-const char* gFS_Main_FragColor =
- " gl_FragColor = fragColor;\n";
-const char* gFS_Main_FragColor_HasColors =
- " gl_FragColor *= outColors;\n";
+ " fragColor = bitmapColor * gamma(texture2D(baseSampler, outTexCoords).a, "
+ "bitmapColor.rgb);\n",
+};
+const char* gFS_Main_FragColor = " gl_FragColor = fragColor;\n";
+const char* gFS_Main_FragColor_HasColors = " gl_FragColor *= outColors;\n";
const char* gFS_Main_FragColor_Blend =
" gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n";
const char* gFS_Main_FragColor_Blend_Swap =
@@ -425,13 +380,12 @@ const char* gFS_Main_ApplyColorOp[3] = {
// None
"",
// Matrix
- " fragColor.rgb /= (fragColor.a + 0.0019);\n" // un-premultiply
+ " fragColor.rgb /= (fragColor.a + 0.0019);\n" // un-premultiply
" fragColor *= colorMatrix;\n"
" fragColor += colorMatrixVector;\n"
- " fragColor.rgb *= (fragColor.a + 0.0019);\n", // re-premultiply
+ " fragColor.rgb *= (fragColor.a + 0.0019);\n", // re-premultiply
// PorterDuff
- " fragColor = blendColors(colorBlend, fragColor);\n"
-};
+ " fragColor = blendColors(colorBlend, fragColor);\n"};
// Note: LTWH (left top width height) -> xyzw
// roundRectPos is now divided by roundRectRadius in vertex shader
@@ -443,13 +397,12 @@ const char* gFS_Main_FragColor_HasRoundRectClip =
// since distance is divided by radius, it's in [0;1] so precision is not an issue
// this also lets us clamp(0.0, 1.0) instead of max() which is cheaper on GPUs
" mediump vec2 dist = clamp(max(fragToLT, fragFromRB), 0.0, 1.0);\n"
- " mediump float linearDist = clamp(roundRectRadius - (length(dist) * roundRectRadius), 0.0, 1.0);\n"
+ " mediump float linearDist = clamp(roundRectRadius - (length(dist) * roundRectRadius), "
+ "0.0, 1.0);\n"
" gl_FragColor *= linearDist;\n";
-const char* gFS_Main_DebugHighlight =
- " gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n";
-const char* gFS_Footer =
- "}\n\n";
+const char* gFS_Main_DebugHighlight = " gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n";
+const char* gFS_Footer = "}\n\n";
///////////////////////////////////////////////////////////////////////////////
// PorterDuff snippets
@@ -480,7 +433,7 @@ const char* gBlendOps[18] = {
"return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n",
// Xor
"return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, "
- "src.a + dst.a - 2.0 * src.a * dst.a);\n",
+ "src.a + dst.a - 2.0 * src.a * dst.a);\n",
// Plus
"return min(src + dst, 1.0);\n",
// Modulate
@@ -489,16 +442,17 @@ const char* gBlendOps[18] = {
"return src + dst - src * dst;\n",
// Overlay
"return clamp(vec4(mix("
- "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
- "src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
- "step(dst.a, 2.0 * dst.rgb)), "
- "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n",
+ "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
+ "src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + "
+ "dst.rgb * (1.0 - src.a), "
+ "step(dst.a, 2.0 * dst.rgb)), "
+ "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n",
// Darken
"return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
- "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
+ "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
// Lighten
"return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
- "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
+ "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
};
///////////////////////////////////////////////////////////////////////////////
@@ -507,8 +461,7 @@ const char* gBlendOps[18] = {
ProgramCache::ProgramCache(const Extensions& extensions)
: mHasES3(extensions.getMajorGlVersion() >= 3)
- , mHasLinearBlending(extensions.hasLinearBlending()) {
-}
+ , mHasLinearBlending(extensions.hasLinearBlending()) {}
ProgramCache::~ProgramCache() {
clear();
@@ -605,7 +558,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
}
// Begin the shader
- shader.append(gVS_Main); {
+ shader.append(gVS_Main);
+ {
if (description.hasTextureTransform) {
shader.append(gVS_Main_OutTransformedTexCoords);
} else if (description.hasTexture || description.hasExternalTexture) {
@@ -637,8 +591,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
return shader;
}
-static bool shaderOp(const ProgramDescription& description, String8& shader,
- const int modulateOp, const char** snippets) {
+static bool shaderOp(const ProgramDescription& description, String8& shader, const int modulateOp,
+ const char** snippets) {
int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
op = op * 2 + description.hasGammaCorrection;
shader.append(snippets[op]);
@@ -652,8 +606,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (blendFramebuffer) {
shader.append(gFS_Header_Extension_FramebufferFetch);
}
- if (description.hasExternalTexture
- || (description.hasBitmap && description.isShaderBitmapExternal)) {
+ if (description.hasExternalTexture ||
+ (description.hasBitmap && description.isShaderBitmapExternal)) {
shader.append(gFS_Header_Extension_ExternalTexture);
}
@@ -682,7 +636,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
// Uniforms
int modulateOp = MODULATE_OP_NO_MODULATE;
const bool singleColor = !description.hasTexture && !description.hasExternalTexture &&
- !description.hasGradient && !description.hasBitmap;
+ !description.hasGradient && !description.hasBitmap;
if (description.modulate || singleColor) {
shader.append(gFS_Uniforms_Color);
@@ -701,7 +655,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
if (description.hasGammaCorrection) {
- shader.appendFormat(gFS_Gamma_Preamble, Properties::textGamma, 1.0f / Properties::textGamma);
+ shader.appendFormat(gFS_Gamma_Preamble, Properties::textGamma,
+ 1.0f / Properties::textGamma);
}
if (description.hasBitmap) {
@@ -731,17 +686,19 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (description.useShaderBasedWrap) {
generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
}
- if (description.hasGradient || description.hasLinearTexture
- || description.hasColorSpaceConversion) {
+ if (description.hasGradient || description.hasLinearTexture ||
+ description.hasColorSpaceConversion) {
shader.append(gFS_sRGB_TransferFunctions);
}
if (description.hasBitmap || ((description.hasTexture || description.hasExternalTexture) &&
- !description.hasAlpha8Texture)) {
+ !description.hasAlpha8Texture)) {
shader.append(gFS_TransferFunction[static_cast<int>(description.transferFunction)]);
- shader.append(gFS_OETF[(description.hasLinearTexture || description.hasColorSpaceConversion)
- && !mHasLinearBlending]);
+ shader.append(
+ gFS_OETF[(description.hasLinearTexture || description.hasColorSpaceConversion) &&
+ !mHasLinearBlending]);
shader.append(gFS_ColorConvert[description.hasColorSpaceConversion
- ? 1 + description.hasTranslucentConversion : 0]);
+ ? 1 + description.hasTranslucentConversion
+ : 0]);
}
if (description.hasGradient) {
shader.append(gFS_GradientFunctions);
@@ -749,13 +706,14 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
// Begin the shader
- shader.append(gFS_Main); {
+ shader.append(gFS_Main);
+ {
// Stores the result in fragColor directly
if (description.hasTexture || description.hasExternalTexture) {
if (description.hasAlpha8Texture) {
if (!description.hasGradient && !description.hasBitmap) {
- shader.append(
- gFS_Main_FetchA8Texture[modulateOp * 2 + description.hasGammaCorrection]);
+ shader.append(gFS_Main_FetchA8Texture[modulateOp * 2 +
+ description.hasGammaCorrection]);
}
} else {
shader.append(gFS_Main_FetchTexture[modulateOp]);
@@ -783,15 +741,15 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
} else {
shader.append(gFS_Main_BlendShadersGB);
}
- applyModulate = shaderOp(description, shader, modulateOp,
- gFS_Main_BlendShaders_Modulate);
+ applyModulate =
+ shaderOp(description, shader, modulateOp, gFS_Main_BlendShaders_Modulate);
} else {
if (description.hasGradient) {
- applyModulate = shaderOp(description, shader, modulateOp,
- gFS_Main_GradientShader_Modulate);
+ applyModulate =
+ shaderOp(description, shader, modulateOp, gFS_Main_GradientShader_Modulate);
} else if (description.hasBitmap) {
- applyModulate = shaderOp(description, shader, modulateOp,
- gFS_Main_BitmapShader_Modulate);
+ applyModulate =
+ shaderOp(description, shader, modulateOp, gFS_Main_BitmapShader_Modulate);
}
}
@@ -818,8 +776,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (!blendFramebuffer) {
shader.append(gFS_Main_FragColor);
} else {
- shader.append(!description.swapSrcDst ?
- gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap);
+ shader.append(!description.swapSrcDst ? gFS_Main_FragColor_Blend
+ : gFS_Main_FragColor_Blend_Swap);
}
if (description.hasColors) {
shader.append(gFS_Main_FragColor_HasColors);
@@ -835,8 +793,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Footer);
#if DEBUG_PROGRAMS
- PROGRAM_LOGD("*** Generated fragment shader:\n\n");
- printLongString(shader);
+ PROGRAM_LOGD("*** Generated fragment shader:\n\n");
+ printLongString(shader);
#endif
return shader;
@@ -903,5 +861,5 @@ void ProgramCache::printLongString(const String8& shader) const {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index ee76f22f35d4..488a4994ba95 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -60,9 +60,9 @@ private:
const bool mHasES3;
const bool mHasLinearBlending;
-}; // class ProgramCache
+}; // class ProgramCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_PROGRAM_CACHE_H
+#endif // ANDROID_HWUI_PROGRAM_CACHE_H
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index acc75393ebcf..0a6c45beedf9 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -51,15 +51,26 @@ int Properties::overrideSpotShadowStrength = -1;
ProfileType Properties::sProfileType = ProfileType::None;
bool Properties::sDisableProfileBars = false;
RenderPipelineType Properties::sRenderPipelineType = RenderPipelineType::NotInitialized;
+bool Properties::enableHighContrastText = false;
bool Properties::waitForGpuCompletion = false;
bool Properties::forceDrawFrame = false;
bool Properties::filterOutTestOverhead = false;
bool Properties::disableVsync = false;
+bool Properties::skpCaptureEnabled = false;
+bool Properties::enableRTAnimations = true;
+
+bool Properties::runningInEmulator = false;
+bool Properties::debuggingEnabled = false;
+bool Properties::isolatedProcess = false;
+
+int Properties::contextPriority = 0;
static int property_get_int(const char* key, int defaultValue) {
- char buf[PROPERTY_VALUE_MAX] = {'\0',};
+ char buf[PROPERTY_VALUE_MAX] = {
+ '\0',
+ };
if (property_get(key, buf, "") > 0) {
return atoi(buf);
@@ -119,7 +130,7 @@ bool Properties::load() {
showDirtyRegions = property_get_bool(PROPERTY_DEBUG_SHOW_DIRTY_REGIONS, false);
- debugLevel = (DebugLevel) property_get_int(PROPERTY_DEBUG, kDebugDisabled);
+ debugLevel = (DebugLevel)property_get_int(PROPERTY_DEBUG, kDebugDisabled);
skipEmptyFrames = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, true);
useBufferAge = property_get_bool(PROPERTY_USE_BUFFER_AGE, true);
@@ -127,9 +138,12 @@ bool Properties::load() {
filterOutTestOverhead = property_get_bool(PROPERTY_FILTER_TEST_OVERHEAD, false);
- return (prevDebugLayersUpdates != debugLayersUpdates)
- || (prevDebugOverdraw != debugOverdraw)
- || (prevDebugStencilClip != debugStencilClip);
+ skpCaptureEnabled = debuggingEnabled && property_get_bool(PROPERTY_CAPTURE_SKP_ENABLED, false);
+
+ runningInEmulator = property_get_bool(PROPERTY_QEMU_KERNEL, false);
+
+ return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) ||
+ (prevDebugStencilClip != debugStencilClip);
}
void Properties::overrideProperty(const char* name, const char* value) {
@@ -172,35 +186,40 @@ ProfileType Properties::getProfileType() {
}
RenderPipelineType Properties::getRenderPipelineType() {
- if (RenderPipelineType::NotInitialized != sRenderPipelineType) {
+ if (sRenderPipelineType != RenderPipelineType::NotInitialized) {
return sRenderPipelineType;
}
char prop[PROPERTY_VALUE_MAX];
- property_get(PROPERTY_RENDERER, prop, "opengl");
- if (!strcmp(prop, "skiagl") ) {
+ property_get(PROPERTY_RENDERER, prop, "skiagl");
+ if (!strcmp(prop, "skiagl")) {
ALOGD("Skia GL Pipeline");
sRenderPipelineType = RenderPipelineType::SkiaGL;
- } else if (!strcmp(prop, "skiavk") ) {
+ } else if (!strcmp(prop, "skiavk")) {
ALOGD("Skia Vulkan Pipeline");
sRenderPipelineType = RenderPipelineType::SkiaVulkan;
- } else { //"opengl"
+ } else { //"opengl"
ALOGD("HWUI GL Pipeline");
sRenderPipelineType = RenderPipelineType::OpenGL;
}
return sRenderPipelineType;
}
-#ifdef HWUI_GLES_WRAP_ENABLED
void Properties::overrideRenderPipelineType(RenderPipelineType type) {
+#if !defined(HWUI_GLES_WRAP_ENABLED)
+ // If we're doing actual rendering then we can't change the renderer after it's been set.
+ // Unit tests can freely change this as often as it wants, though, as there's no actual
+ // GL rendering happening
+ if (sRenderPipelineType != RenderPipelineType::NotInitialized) {
+ return;
+ }
+#endif
sRenderPipelineType = type;
}
-#endif
bool Properties::isSkiaEnabled() {
auto renderType = getRenderPipelineType();
- return RenderPipelineType::SkiaGL == renderType
- || RenderPipelineType::SkiaVulkan == renderType;
+ return RenderPipelineType::SkiaGL == renderType || RenderPipelineType::SkiaVulkan == renderType;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 47ae9e912127..764c50259540 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HWUI_PROPERTIES_H
#define ANDROID_HWUI_PROPERTIES_H
+#include <cutils/compiler.h>
#include <cutils/properties.h>
/**
@@ -164,38 +165,42 @@ enum DebugLevel {
*/
#define PROPERTY_RENDERER "debug.hwui.renderer"
+/**
+ * Allows to collect a recording of Skia drawing commands.
+ */
+#define PROPERTY_CAPTURE_SKP_ENABLED "debug.hwui.capture_skp_enabled"
+
+/**
+ * Defines how many frames in a sequence to capture.
+ */
+#define PROPERTY_CAPTURE_SKP_FRAMES "debug.hwui.capture_skp_frames"
+
+/**
+ * File name and location, where a SKP recording will be saved.
+ */
+#define PROPERTY_CAPTURE_SKP_FILENAME "debug.hwui.skp_filename"
+
+/**
+ * Property for whether this is running in the emulator.
+ */
+#define PROPERTY_QEMU_KERNEL "ro.kernel.qemu"
+
///////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////
// Converts a number of mega-bytes into bytes
-#define MB(s) ((s) * 1024 * 1024)
+#define MB(s) ((s)*1024 * 1024)
// Converts a number of kilo-bytes into bytes
-#define KB(s) ((s) * 1024)
+#define KB(s) ((s)*1024)
-enum class ProfileType {
- None,
- Console,
- Bars
-};
+enum class ProfileType { None, Console, Bars };
-enum class OverdrawColorSet {
- Default = 0,
- Deuteranomaly
-};
+enum class OverdrawColorSet { Default = 0, Deuteranomaly };
-enum class StencilClipDebug {
- Hide,
- ShowHighlight,
- ShowRegion
-};
+enum class StencilClipDebug { Hide, ShowHighlight, ShowRegion };
-enum class RenderPipelineType {
- OpenGL = 0,
- SkiaGL,
- SkiaVulkan,
- NotInitialized = 128
-};
+enum class RenderPipelineType { OpenGL = 0, SkiaGL, SkiaVulkan, NotInitialized = 128 };
/**
* Renderthread-only singleton which manages several static rendering properties. Most of these
@@ -234,9 +239,11 @@ public:
static int overrideSpotShadowStrength;
static ProfileType getProfileType();
- static RenderPipelineType getRenderPipelineType();
+ ANDROID_API static RenderPipelineType getRenderPipelineType();
static bool isSkiaEnabled();
+ ANDROID_API static bool enableHighContrastText;
+
// Should be used only by test apps
static bool waitForGpuCompletion;
static bool forceDrawFrame;
@@ -251,18 +258,28 @@ public:
// created after changing this.
static bool disableVsync;
+ static bool skpCaptureEnabled;
+
+ // For experimentation b/68769804
+ ANDROID_API static bool enableRTAnimations;
+
// Used for testing only to change the render pipeline.
-#ifdef HWUI_GLES_WRAP_ENABLED
static void overrideRenderPipelineType(RenderPipelineType);
-#endif
+
+ static bool runningInEmulator;
+
+ ANDROID_API static bool debuggingEnabled;
+ ANDROID_API static bool isolatedProcess;
+
+ ANDROID_API static int contextPriority;
private:
static ProfileType sProfileType;
static bool sDisableProfileBars;
static RenderPipelineType sRenderPipelineType;
-}; // class Caches
+}; // class Caches
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_PROPERTIES_H
+#endif // ANDROID_HWUI_PROPERTIES_H
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
index e3258e3c1a48..65a5aa4c0112 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -23,11 +23,11 @@ namespace android {
namespace uirenderer {
void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
- Interpolator* interpolator, nsecs_t startDelay, nsecs_t duration, int repeatCount,
- RepeatMode repeatMode) {
-
- PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder,
- interpolator, startDelay, duration, repeatCount, repeatMode);
+ Interpolator* interpolator, nsecs_t startDelay,
+ nsecs_t duration, int repeatCount,
+ RepeatMode repeatMode) {
+ PropertyAnimator* animator = new PropertyAnimator(
+ propertyValuesHolder, interpolator, startDelay, duration, repeatCount, repeatMode);
mAnimators.emplace_back(animator);
// Check whether any child animator is infinite after adding it them to the set.
@@ -36,8 +36,7 @@ void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* proper
}
}
-PropertyValuesAnimatorSet::PropertyValuesAnimatorSet()
- : BaseRenderNodeAnimator(1.0f) {
+PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() : BaseRenderNodeAnimator(1.0f) {
setStartValue(0);
mLastFraction = 0.0f;
setInterpolator(new LinearInterpolator());
@@ -77,7 +76,7 @@ void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
// have the final say on what the property value should be.
(*it)->setFraction(0, 0);
}
- } else {
+ } else {
for (auto& anim : mAnimators) {
anim->setCurrentPlayTime(playTime);
}
@@ -116,9 +115,8 @@ void PropertyValuesAnimatorSet::init() {
// Sort the animators by their total duration. Note that all the animators in the set start at
// the same time, so the ones with longer total duration (which includes start delay) will
// be the ones that end later.
- std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) {
- return a->getTotalDuration() < b->getTotalDuration();
- });
+ std::sort(mAnimators.begin(), mAnimators.end(),
+ [](auto& a, auto& b) { return a->getTotalDuration() < b->getTotalDuration(); });
mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration();
mInitialized = true;
}
@@ -128,17 +126,19 @@ uint32_t PropertyValuesAnimatorSet::dirtyMask() {
}
PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator,
- nsecs_t startDelay, nsecs_t duration, int repeatCount,
- RepeatMode repeatMode)
- : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay),
- mDuration(duration) {
+ nsecs_t startDelay, nsecs_t duration, int repeatCount,
+ RepeatMode repeatMode)
+ : mPropertyValuesHolder(holder)
+ , mInterpolator(interpolator)
+ , mStartDelay(startDelay)
+ , mDuration(duration) {
if (repeatCount < 0) {
mRepeatCount = UINT32_MAX;
} else {
mRepeatCount = repeatCount;
}
mRepeatMode = repeatMode;
- mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay;
+ mTotalDuration = ((nsecs_t)mRepeatCount + 1) * mDuration + mStartDelay;
}
void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
@@ -155,7 +155,7 @@ void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
} else {
// play time here is in range [mStartDelay, mTotalDuration)
iteration = (playTime - mStartDelay) / mDuration;
- currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float) mDuration;
+ currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float)mDuration;
}
setFraction(currentIterationFraction, iteration);
}
@@ -182,6 +182,5 @@ void PropertyAnimator::setFraction(float fraction, long iteration) {
void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) {
mSet->onFinished(animator);
}
-
}
}
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index a5d9e869196f..e4214b22d1cc 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -17,8 +17,8 @@
#pragma once
#include "Animator.h"
-#include "PropertyValuesHolder.h"
#include "Interpolator.h"
+#include "PropertyValuesHolder.h"
namespace android {
namespace uirenderer {
@@ -26,11 +26,9 @@ namespace uirenderer {
class PropertyAnimator {
public:
PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay,
- nsecs_t duration, int repeatCount, RepeatMode repeatMode);
+ nsecs_t duration, int repeatCount, RepeatMode repeatMode);
void setCurrentPlayTime(nsecs_t playTime);
- nsecs_t getTotalDuration() {
- return mTotalDuration;
- }
+ nsecs_t getTotalDuration() { return mTotalDuration; }
// fraction range: [0, 1], iteration range [0, repeatCount]
void setFraction(float fraction, long iteration);
@@ -57,8 +55,8 @@ public:
virtual void end() override;
void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
- Interpolator* interpolators, int64_t startDelays,
- nsecs_t durations, int repeatCount, RepeatMode repeatMode);
+ Interpolator* interpolators, int64_t startDelays, nsecs_t durations,
+ int repeatCount, RepeatMode repeatMode);
virtual uint32_t dirtyMask();
bool isInfinite() { return mIsInfinite; }
void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; }
@@ -77,7 +75,7 @@ private:
void onFinished(BaseRenderNodeAnimator* animator);
// Listener set from outside
sp<AnimationListener> mOneShotListener;
- std::vector< std::unique_ptr<PropertyAnimator> > mAnimators;
+ std::vector<std::unique_ptr<PropertyAnimator> > mAnimators;
float mLastFraction = 0.0f;
bool mInitialized = false;
sp<VectorDrawableRoot> mVectorDrawable;
@@ -96,5 +94,5 @@ private:
PropertyValuesAnimatorSet* mSet;
};
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
index 2a03e6a3ebc5..35526255759f 100644
--- a/libs/hwui/PropertyValuesHolder.cpp
+++ b/libs/hwui/PropertyValuesHolder.cpp
@@ -27,7 +27,7 @@ namespace uirenderer {
using namespace VectorDrawable;
inline constexpr float lerp(float fromValue, float toValue, float fraction) {
- return float (fromValue * (1 - fraction) + toValue * fraction);
+ return float(fromValue * (1 - fraction) + toValue * fraction);
}
inline constexpr float linearize(U8CPU component) {
@@ -35,25 +35,23 @@ inline constexpr float linearize(U8CPU component) {
}
// TODO: Add a test for this
-void ColorEvaluator::evaluate(SkColor* outColor,
- const SkColor& fromColor, const SkColor& toColor, float fraction) const {
+void ColorEvaluator::evaluate(SkColor* outColor, const SkColor& fromColor, const SkColor& toColor,
+ float fraction) const {
float a = lerp(SkColorGetA(fromColor) / 255.0f, SkColorGetA(toColor) / 255.0f, fraction);
float r = lerp(linearize(SkColorGetR(fromColor)), linearize(SkColorGetR(toColor)), fraction);
float g = lerp(linearize(SkColorGetG(fromColor)), linearize(SkColorGetG(toColor)), fraction);
float b = lerp(linearize(SkColorGetB(fromColor)), linearize(SkColorGetB(toColor)), fraction);
- *outColor = SkColorSetARGB(
- (U8CPU) roundf(a * 255.0f),
- (U8CPU) roundf(OECF_sRGB(r) * 255.0f),
- (U8CPU) roundf(OECF_sRGB(g) * 255.0f),
- (U8CPU) roundf(OECF_sRGB(b) * 255.0f));
+ *outColor = SkColorSetARGB((U8CPU)roundf(a * 255.0f), (U8CPU)roundf(OECF_sRGB(r) * 255.0f),
+ (U8CPU)roundf(OECF_sRGB(g) * 255.0f),
+ (U8CPU)roundf(OECF_sRGB(b) * 255.0f));
}
-void PathEvaluator::evaluate(PathData* out,
- const PathData& from, const PathData& to, float fraction) const {
+void PathEvaluator::evaluate(PathData* out, const PathData& from, const PathData& to,
+ float fraction) const {
VectorDrawableUtils::interpolatePaths(out, from, to, fraction);
}
-template<typename T>
+template <typename T>
const T PropertyValuesHolderImpl<T>::getValueFromData(float fraction) const {
if (mDataSource.size() == 0) {
LOG_ALWAYS_FATAL("No data source is defined");
@@ -75,7 +73,7 @@ const T PropertyValuesHolderImpl<T>::getValueFromData(float fraction) const {
return value;
}
-template<typename T>
+template <typename T>
const T PropertyValuesHolderImpl<T>::calculateAnimatedValue(float fraction) const {
if (mDataSource.size() > 0) {
return getValueFromData(fraction);
@@ -111,5 +109,5 @@ void RootAlphaPropertyValuesHolder::setFraction(float fraction) {
mTree->mutateProperties()->setRootAlpha(animatedValue);
}
-} // namepace uirenderer
-} // namespace android
+} // namepace uirenderer
+} // namespace android
diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h
index 432f8ba82afb..0a799d3c0b5c 100644
--- a/libs/hwui/PropertyValuesHolder.h
+++ b/libs/hwui/PropertyValuesHolder.h
@@ -43,8 +43,8 @@ public:
class FloatEvaluator : public Evaluator<float> {
public:
- virtual void evaluate(float* out, const float& from, const float& to, float fraction)
- const override {
+ virtual void evaluate(float* out, const float& from, const float& to,
+ float fraction) const override {
*out = from * (1 - fraction) + to * fraction;
}
};
@@ -52,20 +52,19 @@ public:
class ANDROID_API ColorEvaluator : public Evaluator<SkColor> {
public:
virtual void evaluate(SkColor* outColor, const SkColor& from, const SkColor& to,
- float fraction) const override;
+ float fraction) const override;
};
class ANDROID_API PathEvaluator : public Evaluator<PathData> {
- virtual void evaluate(PathData* out, const PathData& from, const PathData& to, float fraction)
- const override;
+ virtual void evaluate(PathData* out, const PathData& from, const PathData& to,
+ float fraction) const override;
};
template <typename T>
class ANDROID_API PropertyValuesHolderImpl : public PropertyValuesHolder {
public:
PropertyValuesHolderImpl(const T& startValue, const T& endValue)
- : mStartValue(startValue)
- , mEndValue(endValue) {}
+ : mStartValue(startValue), mEndValue(endValue) {}
void setPropertyDataSource(T* dataSource, int length) {
mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length);
}
@@ -74,27 +73,27 @@ public:
// Convenient method to favor getting animated value from data source. If no data source is set
// fall back to linear interpolation.
const T calculateAnimatedValue(float fraction) const;
+
protected:
- std::unique_ptr<Evaluator<T>> mEvaluator = nullptr;
- // This contains uniformly sampled data throughout the animation duration. The first element
- // should be the start value and the last should be the end value of the animation. When the
- // data source is set, we'll favor data source over the linear interpolation of start/end value
- // for calculation of animated value.
- std::vector<T> mDataSource;
- T mStartValue;
- T mEndValue;
+ std::unique_ptr<Evaluator<T>> mEvaluator = nullptr;
+ // This contains uniformly sampled data throughout the animation duration. The first element
+ // should be the start value and the last should be the end value of the animation. When the
+ // data source is set, we'll favor data source over the linear interpolation of start/end value
+ // for calculation of animated value.
+ std::vector<T> mDataSource;
+ T mStartValue;
+ T mEndValue;
};
class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
public:
GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue,
- float endValue)
- : PropertyValuesHolderImpl(startValue, endValue)
- , mGroup(ptr)
- , mPropertyId(propertyId) {
+ float endValue)
+ : PropertyValuesHolderImpl(startValue, endValue), mGroup(ptr), mPropertyId(propertyId) {
mEvaluator.reset(new FloatEvaluator());
}
void setFraction(float fraction) override;
+
private:
VectorDrawable::Group* mGroup;
int mPropertyId;
@@ -103,7 +102,7 @@ private:
class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolderImpl<SkColor> {
public:
FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId,
- SkColor startValue, SkColor endValue)
+ SkColor startValue, SkColor endValue)
: PropertyValuesHolderImpl(startValue, endValue)
, mFullPath(ptr)
, mPropertyId(propertyId) {
@@ -111,6 +110,7 @@ public:
}
void setFraction(float fraction) override;
static SkColor interpolateColors(SkColor fromColor, SkColor toColor, float fraction);
+
private:
VectorDrawable::FullPath* mFullPath;
int mPropertyId;
@@ -119,13 +119,14 @@ private:
class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
public:
FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue,
- float endValue)
+ float endValue)
: PropertyValuesHolderImpl(startValue, endValue)
, mFullPath(ptr)
, mPropertyId(propertyId) {
mEvaluator.reset(new FloatEvaluator());
};
void setFraction(float fraction) override;
+
private:
VectorDrawable::FullPath* mFullPath;
int mPropertyId;
@@ -134,12 +135,12 @@ private:
class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolderImpl<PathData> {
public:
PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue,
- PathData* endValue)
- : PropertyValuesHolderImpl(*startValue, *endValue)
- , mPath(ptr) {
+ PathData* endValue)
+ : PropertyValuesHolderImpl(*startValue, *endValue), mPath(ptr) {
mEvaluator.reset(new PathEvaluator());
};
void setFraction(float fraction) override;
+
private:
VectorDrawable::Path* mPath;
PathData mPathData;
@@ -148,11 +149,11 @@ private:
class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
public:
RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue)
- : PropertyValuesHolderImpl(startValue, endValue)
- , mTree(tree) {
+ : PropertyValuesHolderImpl(startValue, endValue), mTree(tree) {
mEvaluator.reset(new FloatEvaluator());
}
void setFraction(float fraction) override;
+
private:
VectorDrawable::Tree* mTree;
};
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index 7cf426228af6..ad3a8b690617 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -16,8 +16,8 @@
#pragma once
-#include "renderthread/RenderThread.h"
#include "Rect.h"
+#include "renderthread/RenderThread.h"
#include <SkBitmap.h>
@@ -41,8 +41,7 @@ public:
/**
* Copies the surface's most recently queued buffer into the provided bitmap.
*/
- virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
- SkBitmap* bitmap) = 0;
+ virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) = 0;
virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) = 0;
protected:
@@ -52,5 +51,5 @@ protected:
renderthread::RenderThread& mRenderThread;
};
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index 3b87aef942b6..2d0185aaa9e2 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -16,15 +16,15 @@
#pragma once
-#include "font/FontUtil.h"
#include "GlLayer.h"
#include "Matrix.h"
#include "Rect.h"
#include "RenderNode.h"
#include "TessellationCache.h"
+#include "Vector.h"
+#include "font/FontUtil.h"
#include "utils/LinearAllocator.h"
#include "utils/PaintUtils.h"
-#include "Vector.h"
#include <androidfw/ResourceTypes.h>
@@ -73,39 +73,40 @@ class Tree;
* MERGEABLE - These ops can be recorded into DisplayLists and rendered individually, or merged
* under certain circumstances.
*/
-#define MAP_OPS_BASED_ON_TYPE(PRE_RENDER_OP_FN, RENDER_ONLY_OP_FN, UNMERGEABLE_OP_FN, MERGEABLE_OP_FN) \
- PRE_RENDER_OP_FN(RenderNodeOp) \
- PRE_RENDER_OP_FN(CirclePropsOp) \
- PRE_RENDER_OP_FN(RoundRectPropsOp) \
- PRE_RENDER_OP_FN(BeginLayerOp) \
- PRE_RENDER_OP_FN(EndLayerOp) \
- PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \
- PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
- PRE_RENDER_OP_FN(VectorDrawableOp) \
- \
- RENDER_ONLY_OP_FN(ShadowOp) \
- RENDER_ONLY_OP_FN(LayerOp) \
- RENDER_ONLY_OP_FN(CopyToLayerOp) \
- RENDER_ONLY_OP_FN(CopyFromLayerOp) \
- \
- UNMERGEABLE_OP_FN(ArcOp) \
- UNMERGEABLE_OP_FN(BitmapMeshOp) \
- UNMERGEABLE_OP_FN(BitmapRectOp) \
- UNMERGEABLE_OP_FN(ColorOp) \
- UNMERGEABLE_OP_FN(FunctorOp) \
- UNMERGEABLE_OP_FN(LinesOp) \
- UNMERGEABLE_OP_FN(OvalOp) \
- UNMERGEABLE_OP_FN(PathOp) \
- UNMERGEABLE_OP_FN(PointsOp) \
- UNMERGEABLE_OP_FN(RectOp) \
- UNMERGEABLE_OP_FN(RoundRectOp) \
- UNMERGEABLE_OP_FN(SimpleRectsOp) \
- UNMERGEABLE_OP_FN(TextOnPathOp) \
- UNMERGEABLE_OP_FN(TextureLayerOp) \
- \
- MERGEABLE_OP_FN(BitmapOp) \
- MERGEABLE_OP_FN(PatchOp) \
- MERGEABLE_OP_FN(TextOp)
+#define MAP_OPS_BASED_ON_TYPE(PRE_RENDER_OP_FN, RENDER_ONLY_OP_FN, UNMERGEABLE_OP_FN, \
+ MERGEABLE_OP_FN) \
+ PRE_RENDER_OP_FN(RenderNodeOp) \
+ PRE_RENDER_OP_FN(CirclePropsOp) \
+ PRE_RENDER_OP_FN(RoundRectPropsOp) \
+ PRE_RENDER_OP_FN(BeginLayerOp) \
+ PRE_RENDER_OP_FN(EndLayerOp) \
+ PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \
+ PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
+ PRE_RENDER_OP_FN(VectorDrawableOp) \
+ \
+ RENDER_ONLY_OP_FN(ShadowOp) \
+ RENDER_ONLY_OP_FN(LayerOp) \
+ RENDER_ONLY_OP_FN(CopyToLayerOp) \
+ RENDER_ONLY_OP_FN(CopyFromLayerOp) \
+ \
+ UNMERGEABLE_OP_FN(ArcOp) \
+ UNMERGEABLE_OP_FN(BitmapMeshOp) \
+ UNMERGEABLE_OP_FN(BitmapRectOp) \
+ UNMERGEABLE_OP_FN(ColorOp) \
+ UNMERGEABLE_OP_FN(FunctorOp) \
+ UNMERGEABLE_OP_FN(LinesOp) \
+ UNMERGEABLE_OP_FN(OvalOp) \
+ UNMERGEABLE_OP_FN(PathOp) \
+ UNMERGEABLE_OP_FN(PointsOp) \
+ UNMERGEABLE_OP_FN(RectOp) \
+ UNMERGEABLE_OP_FN(RoundRectOp) \
+ UNMERGEABLE_OP_FN(SimpleRectsOp) \
+ UNMERGEABLE_OP_FN(TextOnPathOp) \
+ UNMERGEABLE_OP_FN(TextureLayerOp) \
+ \
+ MERGEABLE_OP_FN(BitmapOp) \
+ MERGEABLE_OP_FN(PatchOp) \
+ MERGEABLE_OP_FN(TextOp)
/**
* LUT generators, which will insert nullptr for unsupported ops
@@ -113,16 +114,16 @@ class Tree;
#define NULLPTR_OP_FN(Type) nullptr,
#define BUILD_DEFERRABLE_OP_LUT(OP_FN) \
- { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
+ { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
#define BUILD_MERGEABLE_OP_LUT(OP_FN) \
- { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) }
+ { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) }
#define BUILD_RENDERABLE_OP_LUT(OP_FN) \
- { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
+ { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
#define BUILD_FULL_OP_LUT(OP_FN) \
- { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
+ { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
/**
* Op mapping functions, which skip unsupported ops.
@@ -131,30 +132,29 @@ class Tree;
*/
#define NULL_OP_FN(Type)
-#define MAP_DEFERRABLE_OPS(OP_FN) \
- MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
+#define MAP_DEFERRABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
-#define MAP_MERGEABLE_OPS(OP_FN) \
- MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
+#define MAP_MERGEABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
-#define MAP_RENDERABLE_OPS(OP_FN) \
- MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
+#define MAP_RENDERABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
// Generate OpId enum
#define IDENTITY_FN(Type) Type,
namespace RecordedOpId {
- enum {
- MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN)
- Count,
- };
+enum {
+ MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN) Count,
+};
}
-static_assert(RecordedOpId::RenderNodeOp == 0,
- "First index must be zero for LUTs to work");
+static_assert(RecordedOpId::RenderNodeOp == 0, "First index must be zero for LUTs to work");
-#define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint
-#define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip
+#define BASE_PARAMS \
+ const Rect &unmappedBounds, const Matrix4 &localMatrix, const ClipBase *localClip, \
+ const SkPaint *paint
+#define BASE_PARAMS_PAINTLESS \
+ const Rect &unmappedBounds, const Matrix4 &localMatrix, const ClipBase *localClip
#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint)
-#define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr)
+#define SUPER_PAINTLESS(Type) \
+ RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr)
struct RecordedOp {
/* ID from RecordedOpId - generally used for jumping into function tables */
@@ -171,6 +171,7 @@ struct RecordedOp {
/* optional paint, stored in base object to simplify merging logic */
const SkPaint* paint;
+
protected:
RecordedOp(unsigned int opId, BASE_PARAMS)
: opId(opId)
@@ -182,9 +183,8 @@ protected:
struct RenderNodeOp : RecordedOp {
RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
- : SUPER_PAINTLESS(RenderNodeOp)
- , renderNode(renderNode) {}
- RenderNode * renderNode; // not const, since drawing modifies it
+ : SUPER_PAINTLESS(RenderNodeOp), renderNode(renderNode) {}
+ RenderNode* renderNode; // not const, since drawing modifies it
/**
* Holds the transformation between the projection surface ViewGroup and this RenderNode
@@ -204,25 +204,20 @@ struct RenderNodeOp : RecordedOp {
struct ArcOp : RecordedOp {
ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter)
- : SUPER(ArcOp)
- , startAngle(startAngle)
- , sweepAngle(sweepAngle)
- , useCenter(useCenter) {}
+ : SUPER(ArcOp), startAngle(startAngle), sweepAngle(sweepAngle), useCenter(useCenter) {}
const float startAngle;
const float sweepAngle;
const bool useCenter;
};
struct BitmapOp : RecordedOp {
- BitmapOp(BASE_PARAMS, Bitmap* bitmap)
- : SUPER(BitmapOp)
- , bitmap(bitmap) {}
+ BitmapOp(BASE_PARAMS, Bitmap* bitmap) : SUPER(BitmapOp), bitmap(bitmap) {}
Bitmap* bitmap;
};
struct BitmapMeshOp : RecordedOp {
- BitmapMeshOp(BASE_PARAMS, Bitmap* bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors)
+ BitmapMeshOp(BASE_PARAMS, Bitmap* bitmap, int meshWidth, int meshHeight, const float* vertices,
+ const int* colors)
: SUPER(BitmapMeshOp)
, bitmap(bitmap)
, meshWidth(meshWidth)
@@ -238,16 +233,14 @@ struct BitmapMeshOp : RecordedOp {
struct BitmapRectOp : RecordedOp {
BitmapRectOp(BASE_PARAMS, Bitmap* bitmap, const Rect& src)
- : SUPER(BitmapRectOp)
- , bitmap(bitmap)
- , src(src) {}
+ : SUPER(BitmapRectOp), bitmap(bitmap), src(src) {}
Bitmap* bitmap;
const Rect src;
};
struct CirclePropsOp : RecordedOp {
CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
- float* x, float* y, float* radius)
+ float* x, float* y, float* radius)
: RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint)
, x(x)
, y(y)
@@ -278,60 +271,47 @@ struct FunctorOp : RecordedOp {
struct LinesOp : RecordedOp {
LinesOp(BASE_PARAMS, const float* points, const int floatCount)
- : SUPER(LinesOp)
- , points(points)
- , floatCount(floatCount) {}
+ : SUPER(LinesOp), points(points), floatCount(floatCount) {}
const float* points;
const int floatCount;
};
struct OvalOp : RecordedOp {
- OvalOp(BASE_PARAMS)
- : SUPER(OvalOp) {}
+ OvalOp(BASE_PARAMS) : SUPER(OvalOp) {}
};
struct PatchOp : RecordedOp {
PatchOp(BASE_PARAMS, Bitmap* bitmap, const Res_png_9patch* patch)
- : SUPER(PatchOp)
- , bitmap(bitmap)
- , patch(patch) {}
+ : SUPER(PatchOp), bitmap(bitmap), patch(patch) {}
Bitmap* bitmap;
const Res_png_9patch* patch;
};
struct PathOp : RecordedOp {
- PathOp(BASE_PARAMS, const SkPath* path)
- : SUPER(PathOp)
- , path(path) {}
+ PathOp(BASE_PARAMS, const SkPath* path) : SUPER(PathOp), path(path) {}
const SkPath* path;
};
struct PointsOp : RecordedOp {
PointsOp(BASE_PARAMS, const float* points, const int floatCount)
- : SUPER(PointsOp)
- , points(points)
- , floatCount(floatCount) {}
+ : SUPER(PointsOp), points(points), floatCount(floatCount) {}
const float* points;
const int floatCount;
};
struct RectOp : RecordedOp {
- RectOp(BASE_PARAMS)
- : SUPER(RectOp) {}
+ RectOp(BASE_PARAMS) : SUPER(RectOp) {}
};
struct RoundRectOp : RecordedOp {
- RoundRectOp(BASE_PARAMS, float rx, float ry)
- : SUPER(RoundRectOp)
- , rx(rx)
- , ry(ry) {}
+ RoundRectOp(BASE_PARAMS, float rx, float ry) : SUPER(RoundRectOp), rx(rx), ry(ry) {}
const float rx;
const float ry;
};
struct RoundRectPropsOp : RecordedOp {
RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
- float* left, float* top, float* right, float* bottom, float *rx, float *ry)
+ float* left, float* top, float* right, float* bottom, float* rx, float* ry)
: RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint)
, left(left)
, top(top)
@@ -349,8 +329,7 @@ struct RoundRectPropsOp : RecordedOp {
struct VectorDrawableOp : RecordedOp {
VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS)
- : SUPER_PAINTLESS(VectorDrawableOp)
- , vectorDrawable(tree) {}
+ : SUPER_PAINTLESS(VectorDrawableOp), vectorDrawable(tree) {}
VectorDrawable::Tree* vectorDrawable;
};
@@ -366,24 +345,21 @@ struct ShadowOp : RecordedOp {
ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha)
: RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr)
, shadowTask(shadowTask)
- , casterAlpha(casterAlpha) {
- };
+ , casterAlpha(casterAlpha){};
sp<TessellationCache::ShadowTask> shadowTask;
const float casterAlpha;
};
-struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
+struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
- : SUPER(SimpleRectsOp)
- , vertices(vertices)
- , vertexCount(vertexCount) {}
+ : SUPER(SimpleRectsOp), vertices(vertices), vertexCount(vertexCount) {}
Vertex* vertices;
const size_t vertexCount;
};
struct TextOp : RecordedOp {
- TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount,
- float x, float y)
+ TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount, float x,
+ float y)
: SUPER(TextOp)
, glyphs(glyphs)
, positions(positions)
@@ -400,7 +376,8 @@ struct TextOp : RecordedOp {
struct TextOnPathOp : RecordedOp {
// TODO: explicitly define bounds
TextOnPathOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
- const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset, float vOffset)
+ const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset,
+ float vOffset)
: RecordedOp(RecordedOpId::TextOnPathOp, Rect(), localMatrix, localClip, paint)
, glyphs(glyphs)
, glyphCount(glyphCount)
@@ -417,16 +394,13 @@ struct TextOnPathOp : RecordedOp {
struct TextureLayerOp : RecordedOp {
TextureLayerOp(BASE_PARAMS_PAINTLESS, DeferredLayerUpdater* layer)
- : SUPER_PAINTLESS(TextureLayerOp)
- , layerHandle(layer) {}
+ : SUPER_PAINTLESS(TextureLayerOp), layerHandle(layer) {}
// Copy an existing TextureLayerOp, replacing the underlying matrix
TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix)
: RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix,
- op.localClip, op.paint)
- , layerHandle(op.layerHandle) {
-
- }
+ op.localClip, op.paint)
+ , layerHandle(op.layerHandle) {}
DeferredLayerUpdater* layerHandle;
};
@@ -439,8 +413,7 @@ struct TextureLayerOp : RecordedOp {
* and that commands following will render into it.
*/
struct BeginLayerOp : RecordedOp {
- BeginLayerOp(BASE_PARAMS)
- : SUPER(BeginLayerOp) {}
+ BeginLayerOp(BASE_PARAMS) : SUPER(BeginLayerOp) {}
};
/**
@@ -455,22 +428,20 @@ struct EndLayerOp : RecordedOp {
};
struct BeginUnclippedLayerOp : RecordedOp {
- BeginUnclippedLayerOp(BASE_PARAMS)
- : SUPER(BeginUnclippedLayerOp) {}
+ BeginUnclippedLayerOp(BASE_PARAMS) : SUPER(BeginUnclippedLayerOp) {}
};
struct EndUnclippedLayerOp : RecordedOp {
EndUnclippedLayerOp()
- : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
+ : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr,
+ nullptr) {}
};
struct CopyToLayerOp : RecordedOp {
CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
- : RecordedOp(RecordedOpId::CopyToLayerOp,
- op.unmappedBounds,
- op.localMatrix,
- nullptr, // clip intentionally ignored
- op.paint)
+ : RecordedOp(RecordedOpId::CopyToLayerOp, op.unmappedBounds, op.localMatrix,
+ nullptr, // clip intentionally ignored
+ op.paint)
, layerHandle(layerHandle) {}
// Records a handle to the Layer object, since the Layer itself won't be
@@ -478,15 +449,12 @@ struct CopyToLayerOp : RecordedOp {
OffscreenBuffer** layerHandle;
};
-
// draw the parameter layer underneath
struct CopyFromLayerOp : RecordedOp {
CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
- : RecordedOp(RecordedOpId::CopyFromLayerOp,
- op.unmappedBounds,
- op.localMatrix,
- nullptr, // clip intentionally ignored
- op.paint)
+ : RecordedOp(RecordedOpId::CopyFromLayerOp, op.unmappedBounds, op.localMatrix,
+ nullptr, // clip intentionally ignored
+ op.paint)
, layerHandle(layerHandle) {}
// Records a handle to the Layer object, since the Layer itself won't be
@@ -510,7 +478,8 @@ struct LayerOp : RecordedOp {
, colorFilter(paint ? paint->getColorFilter() : nullptr) {}
explicit LayerOp(RenderNode& node)
- : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr)
+ : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()),
+ Matrix4::identity(), nullptr, nullptr)
, layerHandle(node.getLayerHandle())
, alpha(node.properties().layerProperties().alpha() / 255.0f)
, mode(node.properties().layerProperties().xferMode())
@@ -527,5 +496,5 @@ struct LayerOp : RecordedOp {
SkColorFilter* colorFilter;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index d966372a7699..e1df1e7725b5 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -26,19 +26,16 @@ namespace android {
namespace uirenderer {
RecordingCanvas::RecordingCanvas(size_t width, size_t height)
- : mState(*this)
- , mResourceCache(ResourceCache::getInstance()) {
+ : mState(*this), mResourceCache(ResourceCache::getInstance()) {
resetRecording(width, height);
}
RecordingCanvas::~RecordingCanvas() {
- LOG_ALWAYS_FATAL_IF(mDisplayList,
- "Destroyed a RecordingCanvas during a record!");
+ LOG_ALWAYS_FATAL_IF(mDisplayList, "Destroyed a RecordingCanvas during a record!");
}
void RecordingCanvas::resetRecording(int width, int height, RenderNode* node) {
- LOG_ALWAYS_FATAL_IF(mDisplayList,
- "prepareDirty called a second time during a recording!");
+ LOG_ALWAYS_FATAL_IF(mDisplayList, "prepareDirty called a second time during a recording!");
mDisplayList = new DisplayList();
mState.initializeRecordingSaveStack(width, height);
@@ -68,8 +65,7 @@ void RecordingCanvas::insertReorderBarrier(bool enableReorder) {
}
SkCanvas* RecordingCanvas::asSkCanvas() {
- LOG_ALWAYS_FATAL_IF(!mDisplayList,
- "attempting to get an SkCanvas when we are not recording!");
+ LOG_ALWAYS_FATAL_IF(!mDisplayList, "attempting to get an SkCanvas when we are not recording!");
if (!mSkiaCanvasProxy) {
mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
}
@@ -88,8 +84,7 @@ SkCanvas* RecordingCanvas::asSkCanvas() {
// CanvasStateClient implementation
// ----------------------------------------------------------------------------
-void RecordingCanvas::onViewportInitialized() {
-}
+void RecordingCanvas::onViewportInitialized() {}
void RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
if (removed.flags & Snapshot::kFlagIsFboLayer) {
@@ -104,7 +99,7 @@ void RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot
// ----------------------------------------------------------------------------
// Save (layer)
int RecordingCanvas::save(SaveFlags::Flags flags) {
- return mState.save((int) flags);
+ return mState.save((int)flags);
}
void RecordingCanvas::RecordingCanvas::restore() {
@@ -116,7 +111,7 @@ void RecordingCanvas::restoreToCount(int saveCount) {
}
int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SaveFlags::Flags flags) {
+ const SkPaint* paint, SaveFlags::Flags flags) {
// force matrix/clip isolation for layer
flags |= SaveFlags::MatrixClip;
bool clippedLayer = flags & SaveFlags::ClipToLayer;
@@ -134,9 +129,8 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
Rect visibleBounds = unmappedBounds;
previous.transform->mapRect(visibleBounds);
- if (CC_UNLIKELY(!clippedLayer
- && previous.transform->rectToRect()
- && visibleBounds.contains(previous.getRenderTargetClip()))) {
+ if (CC_UNLIKELY(!clippedLayer && previous.transform->rectToRect() &&
+ visibleBounds.contains(previous.getRenderTargetClip()))) {
// unlikely case where an unclipped savelayer is recorded with a clip it can use,
// as none of its unaffected/unclipped area is visible
clippedLayer = true;
@@ -157,18 +151,18 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
layerBounds.doIntersect(unmappedBounds);
}
- int saveValue = mState.save((int) flags);
+ int saveValue = mState.save((int)flags);
Snapshot& snapshot = *mState.writableSnapshot();
// layerBounds is in original bounds space, but clipped by current recording clip
if (!layerBounds.isEmpty() && !unmappedBounds.isEmpty()) {
if (CC_LIKELY(clippedLayer)) {
- auto previousClip = getRecordedClip(); // capture before new snapshot clip has changed
+ auto previousClip = getRecordedClip(); // capture before new snapshot clip has changed
if (addOp(alloc().create_trivial<BeginLayerOp>(
- unmappedBounds,
- *previous.transform, // transform to *draw* with
- previousClip, // clip to *draw* with
- refPaint(paint))) >= 0) {
+ unmappedBounds,
+ *previous.transform, // transform to *draw* with
+ previousClip, // clip to *draw* with
+ refPaint(paint))) >= 0) {
snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer;
snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight());
snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f);
@@ -181,10 +175,8 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
}
} else {
if (addOp(alloc().create_trivial<BeginUnclippedLayerOp>(
- unmappedBounds,
- *mState.currentSnapshot()->transform,
- getRecordedClip(),
- refPaint(paint))) >= 0) {
+ unmappedBounds, *mState.currentSnapshot()->transform, getRecordedClip(),
+ refPaint(paint))) >= 0) {
snapshot.flags |= Snapshot::kFlagIsLayer;
return saveValue;
}
@@ -245,10 +237,7 @@ bool RecordingCanvas::clipPath(const SkPath* path, SkClipOp op) {
// android/graphics/Canvas draw operations
// ----------------------------------------------------------------------------
void RecordingCanvas::drawColor(int color, SkBlendMode mode) {
- addOp(alloc().create_trivial<ColorOp>(
- getRecordedClip(),
- color,
- mode));
+ addOp(alloc().create_trivial<ColorOp>(getRecordedClip(), color, mode));
}
void RecordingCanvas::drawPaint(const SkPaint& paint) {
@@ -269,40 +258,35 @@ static Rect calcBoundsOfPoints(const float* points, int floatCount) {
// Geometry
void RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPaint& paint) {
if (CC_UNLIKELY(floatCount < 2 || paint.nothingToDraw())) return;
- floatCount &= ~0x1; // round down to nearest two
+ floatCount &= ~0x1; // round down to nearest two
addOp(alloc().create_trivial<PointsOp>(
- calcBoundsOfPoints(points, floatCount),
- *mState.currentSnapshot()->transform,
- getRecordedClip(),
- refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
+ calcBoundsOfPoints(points, floatCount), *mState.currentSnapshot()->transform,
+ getRecordedClip(), refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
}
void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPaint& paint) {
if (CC_UNLIKELY(floatCount < 4 || paint.nothingToDraw())) return;
- floatCount &= ~0x3; // round down to nearest four
+ floatCount &= ~0x3; // round down to nearest four
addOp(alloc().create_trivial<LinesOp>(
- calcBoundsOfPoints(points, floatCount),
- *mState.currentSnapshot()->transform,
- getRecordedClip(),
- refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
+ calcBoundsOfPoints(points, floatCount), *mState.currentSnapshot()->transform,
+ getRecordedClip(), refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
}
-void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
+void RecordingCanvas::drawRect(float left, float top, float right, float bottom,
+ const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
- addOp(alloc().create_trivial<RectOp>(
- Rect(left, top, right, bottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint)));
+ addOp(alloc().create_trivial<RectOp>(Rect(left, top, right, bottom),
+ *(mState.currentSnapshot()->transform), getRecordedClip(),
+ refPaint(&paint)));
}
void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
if (rects == nullptr) return;
- Vertex* rectData = (Vertex*) mDisplayList->allocator.create_trivial_array<Vertex>(vertexCount);
+ Vertex* rectData = (Vertex*)mDisplayList->allocator.create_trivial_array<Vertex>(vertexCount);
Vertex* vertex = rectData;
float left = FLT_MAX;
@@ -326,17 +310,15 @@ void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const
bottom = std::max(bottom, b);
}
addOp(alloc().create_trivial<SimpleRectsOp>(
- Rect(left, top, right, bottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(paint), rectData, vertexCount));
+ Rect(left, top, right, bottom), *(mState.currentSnapshot()->transform),
+ getRecordedClip(), refPaint(paint), rectData, vertexCount));
}
void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
- if (paint.getStyle() == SkPaint::kFill_Style
- && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
+ if (paint.getStyle() == SkPaint::kFill_Style &&
+ (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
int count = 0;
Vector<float> rects;
SkRegion::Iterator it(region);
@@ -360,26 +342,23 @@ void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
}
}
-void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) {
+void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx,
+ float ry, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
if (CC_LIKELY(MathUtils::isPositive(rx) || MathUtils::isPositive(ry))) {
- addOp(alloc().create_trivial<RoundRectOp>(
- Rect(left, top, right, bottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint), rx, ry));
+ addOp(alloc().create_trivial<RoundRectOp>(Rect(left, top, right, bottom),
+ *(mState.currentSnapshot()->transform),
+ getRecordedClip(), refPaint(&paint), rx, ry));
} else {
drawRect(left, top, right, bottom, paint);
}
}
-void RecordingCanvas::drawRoundRect(
- CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
- CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
- CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
- CanvasPropertyPaint* paint) {
+void RecordingCanvas::drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
+ CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
+ CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
+ CanvasPropertyPaint* paint) {
mDisplayList->ref(left);
mDisplayList->ref(top);
mDisplayList->ref(right);
@@ -389,11 +368,8 @@ void RecordingCanvas::drawRoundRect(
mDisplayList->ref(paint);
refBitmapsInShader(paint->value.getShader());
addOp(alloc().create_trivial<RoundRectPropsOp>(
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- &paint->value,
- &left->value, &top->value, &right->value, &bottom->value,
- &rx->value, &ry->value));
+ *(mState.currentSnapshot()->transform), getRecordedClip(), &paint->value, &left->value,
+ &top->value, &right->value, &bottom->value, &rx->value, &ry->value));
}
void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
@@ -403,65 +379,54 @@ void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint&
drawOval(x - radius, y - radius, x + radius, y + radius, paint);
}
-void RecordingCanvas::drawCircle(
- CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
- CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+void RecordingCanvas::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
mDisplayList->ref(x);
mDisplayList->ref(y);
mDisplayList->ref(radius);
mDisplayList->ref(paint);
refBitmapsInShader(paint->value.getShader());
- addOp(alloc().create_trivial<CirclePropsOp>(
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- &paint->value,
- &x->value, &y->value, &radius->value));
+ addOp(alloc().create_trivial<CirclePropsOp>(*(mState.currentSnapshot()->transform),
+ getRecordedClip(), &paint->value, &x->value,
+ &y->value, &radius->value));
}
-void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
+void RecordingCanvas::drawOval(float left, float top, float right, float bottom,
+ const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
- addOp(alloc().create_trivial<OvalOp>(
- Rect(left, top, right, bottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint)));
+ addOp(alloc().create_trivial<OvalOp>(Rect(left, top, right, bottom),
+ *(mState.currentSnapshot()->transform), getRecordedClip(),
+ refPaint(&paint)));
}
-void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
+void RecordingCanvas::drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, bool useCenter, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
if (fabs(sweepAngle) >= 360.0f) {
drawOval(left, top, right, bottom, paint);
} else {
addOp(alloc().create_trivial<ArcOp>(
- Rect(left, top, right, bottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint),
- startAngle, sweepAngle, useCenter));
+ Rect(left, top, right, bottom), *(mState.currentSnapshot()->transform),
+ getRecordedClip(), refPaint(&paint), startAngle, sweepAngle, useCenter));
}
}
void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
- addOp(alloc().create_trivial<PathOp>(
- Rect(path.getBounds()),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint), refPath(&path)));
+ addOp(alloc().create_trivial<PathOp>(Rect(path.getBounds()),
+ *(mState.currentSnapshot()->transform), getRecordedClip(),
+ refPaint(&paint), refPath(&path)));
}
void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
mDisplayList->ref(tree);
mDisplayList->vectorDrawables.push_back(tree);
addOp(alloc().create_trivial<VectorDrawableOp>(
- tree,
- Rect(tree->stagingProperties()->getBounds()),
- *(mState.currentSnapshot()->transform),
- getRecordedClip()));
+ tree, Rect(tree->stagingProperties()->getBounds()),
+ *(mState.currentSnapshot()->transform), getRecordedClip()));
}
// Bitmap-based
@@ -472,20 +437,19 @@ void RecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Sk
restore();
}
-void RecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix,
- const SkPaint* paint) {
+void RecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
if (matrix.isIdentity()) {
drawBitmap(bitmap, paint);
- } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
- && MathUtils::isPositive(matrix.getScaleX())
- && MathUtils::isPositive(matrix.getScaleY())) {
+ } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) &&
+ MathUtils::isPositive(matrix.getScaleX()) &&
+ MathUtils::isPositive(matrix.getScaleY())) {
// SkMatrix::isScaleTranslate() not available in L
SkRect src;
SkRect dst;
bitmap.getBounds(&src);
matrix.mapRect(&dst, src);
- drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
- dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+ drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft, dst.fTop,
+ dst.fRight, dst.fBottom, paint);
} else {
save(SaveFlags::Matrix);
concat(matrix);
@@ -494,14 +458,11 @@ void RecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix,
}
}
-void RecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) {
- if (srcLeft == 0 && srcTop == 0
- && srcRight == bitmap.width()
- && srcBottom == bitmap.height()
- && (srcBottom - srcTop == dstBottom - dstTop)
- && (srcRight - srcLeft == dstRight - dstLeft)) {
+void RecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) {
+ if (srcLeft == 0 && srcTop == 0 && srcRight == bitmap.width() && srcBottom == bitmap.height() &&
+ (srcBottom - srcTop == dstBottom - dstTop) && (srcRight - srcLeft == dstRight - dstLeft)) {
// transform simple rect to rect drawing case into position bitmap ops, since they merge
save(SaveFlags::Matrix);
translate(dstLeft, dstTop);
@@ -509,56 +470,55 @@ void RecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
restore();
} else {
addOp(alloc().create_trivial<BitmapRectOp>(
- Rect(dstLeft, dstTop, dstRight, dstBottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(paint), refBitmap(bitmap),
+ Rect(dstLeft, dstTop, dstRight, dstBottom), *(mState.currentSnapshot()->transform),
+ getRecordedClip(), refPaint(paint), refBitmap(bitmap),
Rect(srcLeft, srcTop, srcRight, srcBottom)));
}
}
void RecordingCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) {
+ const float* vertices, const int* colors,
+ const SkPaint* paint) {
int vertexCount = (meshWidth + 1) * (meshHeight + 1);
addOp(alloc().create_trivial<BitmapMeshOp>(
- calcBoundsOfPoints(vertices, vertexCount * 2),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(paint), refBitmap(bitmap), meshWidth, meshHeight,
- refBuffer<float>(vertices, vertexCount * 2), // 2 floats per vertex
- refBuffer<int>(colors, vertexCount))); // 1 color per vertex
+ calcBoundsOfPoints(vertices, vertexCount * 2), *(mState.currentSnapshot()->transform),
+ getRecordedClip(), refPaint(paint), refBitmap(bitmap), meshWidth, meshHeight,
+ refBuffer<float>(vertices, vertexCount * 2), // 2 floats per vertex
+ refBuffer<int>(colors, vertexCount))); // 1 color per vertex
}
void RecordingCanvas::drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& patch,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkPaint* paint) {
- addOp(alloc().create_trivial<PatchOp>(
- Rect(dstLeft, dstTop, dstRight, dstBottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(paint), refBitmap(bitmap), refPatch(&patch)));
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) {
+ addOp(alloc().create_trivial<PatchOp>(Rect(dstLeft, dstTop, dstRight, dstBottom),
+ *(mState.currentSnapshot()->transform), getRecordedClip(),
+ refPaint(paint), refBitmap(bitmap), refPatch(&patch)));
+}
+
+double RecordingCanvas::drawAnimatedImage(AnimatedImageDrawable*) {
+ // Unimplemented
+ return 0;
}
// Text
void RecordingCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int glyphCount, const SkPaint& paint,
- float x, float y, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
- float totalAdvance) {
+ float x, float y, float boundsLeft, float boundsTop,
+ float boundsRight, float boundsBottom, float totalAdvance) {
if (glyphCount <= 0 || paint.nothingToDraw()) return;
uint16_t* glyphs = (glyph_t*)alloc().alloc<glyph_t>(glyphCount * sizeof(glyph_t));
float* positions = (float*)alloc().alloc<float>(2 * glyphCount * sizeof(float));
glyphFunc(glyphs, positions);
// TODO: either must account for text shadow in bounds, or record separate ops for text shadows
- addOp(alloc().create_trivial<TextOp>(
- Rect(boundsLeft, boundsTop, boundsRight, boundsBottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint), glyphs, positions, glyphCount, x, y));
+ addOp(alloc().create_trivial<TextOp>(Rect(boundsLeft, boundsTop, boundsRight, boundsBottom),
+ *(mState.currentSnapshot()->transform), getRecordedClip(),
+ refPaint(&paint), glyphs, positions, glyphCount, x, y));
drawTextDecorations(x, y, totalAdvance, paint);
}
void RecordingCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
- const SkPaint& paint, const SkPath& path, size_t start, size_t end) {
+ const SkPaint& paint, const SkPath& path, size_t start,
+ size_t end) {
uint16_t glyphs[1];
for (size_t i = start; i < end; i++) {
glyphs[0] = layout.getGlyphId(i);
@@ -566,28 +526,23 @@ void RecordingCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOff
float y = vOffset + layout.getY(i);
if (paint.nothingToDraw()) return;
const uint16_t* tempGlyphs = refBuffer<glyph_t>(glyphs, 1);
- addOp(alloc().create_trivial<TextOnPathOp>(
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint), tempGlyphs, 1, refPath(&path), x, y));
+ addOp(alloc().create_trivial<TextOnPathOp>(*(mState.currentSnapshot()->transform),
+ getRecordedClip(), refPaint(&paint), tempGlyphs,
+ 1, refPath(&path), x, y));
}
}
void RecordingCanvas::drawBitmap(Bitmap& bitmap, const SkPaint* paint) {
- addOp(alloc().create_trivial<BitmapOp>(
- Rect(bitmap.width(), bitmap.height()),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(paint), refBitmap(bitmap)));
+ addOp(alloc().create_trivial<BitmapOp>(Rect(bitmap.width(), bitmap.height()),
+ *(mState.currentSnapshot()->transform),
+ getRecordedClip(), refPaint(paint), refBitmap(bitmap)));
}
void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
auto&& stagingProps = renderNode->stagingProperties();
RenderNodeOp* op = alloc().create_trivial<RenderNodeOp>(
Rect(stagingProps.getWidth(), stagingProps.getHeight()),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- renderNode);
+ *(mState.currentSnapshot()->transform), getRecordedClip(), renderNode);
int opIndex = addOp(op);
if (CC_LIKELY(opIndex >= 0)) {
int childIndex = mDisplayList->addChild(op);
@@ -612,18 +567,14 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
// its width, height, transform, etc...!
addOp(alloc().create_trivial<TextureLayerOp>(
Rect(layerHandle->getWidth(), layerHandle->getHeight()),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(), layerHandle));
+ *(mState.currentSnapshot()->transform), getRecordedClip(), layerHandle));
}
-void RecordingCanvas::callDrawGLFunction(Functor* functor,
- GlFunctorLifecycleListener* listener) {
+void RecordingCanvas::callDrawGLFunction(Functor* functor, GlFunctorLifecycleListener* listener) {
mDisplayList->functors.push_back({functor, listener});
mDisplayList->ref(listener);
- addOp(alloc().create_trivial<FunctorOp>(
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- functor));
+ addOp(alloc().create_trivial<FunctorOp>(*(mState.currentSnapshot()->transform),
+ getRecordedClip(), functor));
}
int RecordingCanvas::addOp(RecordedOp* op) {
@@ -676,5 +627,5 @@ void RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index ccdb4b0c1d8e..e663402a80f3 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -40,49 +40,50 @@ struct ClipBase;
class DeferredLayerUpdater;
struct RecordedOp;
-class ANDROID_API RecordingCanvas: public Canvas, public CanvasStateClient {
+class ANDROID_API RecordingCanvas : public Canvas, public CanvasStateClient {
enum class DeferredBarrierType {
None,
InOrder,
OutOfOrder,
};
+
public:
RecordingCanvas(size_t width, size_t height);
virtual ~RecordingCanvas();
virtual void resetRecording(int width, int height, RenderNode* node = nullptr) override;
virtual WARN_UNUSED_RESULT DisplayList* finishRecording() override;
-// ----------------------------------------------------------------------------
-// MISC HWUI OPERATIONS - TODO: CATEGORIZE
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // MISC HWUI OPERATIONS - TODO: CATEGORIZE
+ // ----------------------------------------------------------------------------
virtual void insertReorderBarrier(bool enableReorder) override;
virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(RenderNode* renderNode) override;
virtual void callDrawGLFunction(Functor* functor,
- GlFunctorLifecycleListener* listener) override;
+ GlFunctorLifecycleListener* listener) override;
-// ----------------------------------------------------------------------------
-// CanvasStateClient interface
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // CanvasStateClient interface
+ // ----------------------------------------------------------------------------
virtual void onViewportInitialized() override;
virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override;
virtual GLuint getTargetFbo() const override { return -1; }
-// ----------------------------------------------------------------------------
-// HWUI Canvas draw operations
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // HWUI Canvas draw operations
+ // ----------------------------------------------------------------------------
virtual void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
- CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
- CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
- CanvasPropertyPaint* paint) override;
+ CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
+ CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
+ CanvasPropertyPaint* paint) override;
virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
- CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) override;
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) override;
-// ----------------------------------------------------------------------------
-// android/graphics/Canvas interface
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // android/graphics/Canvas interface
+ // ----------------------------------------------------------------------------
virtual SkCanvas* asSkCanvas() override;
virtual void setBitmap(const SkBitmap& bitmap) override {
@@ -93,14 +94,9 @@ public:
virtual int width() override { return mState.getWidth(); }
virtual int height() override { return mState.getHeight(); }
- virtual void setHighContrastText(bool highContrastText) override {
- mHighContrastText = highContrastText;
- }
- virtual bool isHighContrastText() override { return mHighContrastText; }
-
-// ----------------------------------------------------------------------------
-// android/graphics/Canvas state operations
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // android/graphics/Canvas state operations
+ // ----------------------------------------------------------------------------
// Save (layer)
virtual int getSaveCount() const override { return mState.getSaveCount(); }
virtual int save(SaveFlags::Flags flags) override;
@@ -108,9 +104,9 @@ public:
virtual void restoreToCount(int saveCount) override;
virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
- SaveFlags::Flags flags) override;
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SaveFlags::Flags flags) override {
+ SaveFlags::Flags flags) override;
+ virtual int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
+ SaveFlags::Flags flags) override {
SkPaint paint;
paint.setAlpha(alpha);
return saveLayer(left, top, right, bottom, &paint, flags);
@@ -131,8 +127,7 @@ public:
virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
virtual bool quickRejectPath(const SkPath& path) const override;
- virtual bool clipRect(float left, float top, float right, float bottom,
- SkClipOp op) override;
+ virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override;
virtual bool clipPath(const SkPath* path, SkClipOp op) override;
// Misc
@@ -141,59 +136,65 @@ public:
mDrawFilter.reset(SkSafeRef(filter));
}
-// ----------------------------------------------------------------------------
-// android/graphics/Canvas draw operations
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // android/graphics/Canvas draw operations
+ // ----------------------------------------------------------------------------
virtual void drawColor(int color, SkBlendMode mode) override;
virtual void drawPaint(const SkPaint& paint) override;
// Geometry
virtual void drawPoint(float x, float y, const SkPaint& paint) override {
- float points[2] = { x, y };
+ float points[2] = {x, y};
drawPoints(points, 2, paint);
}
virtual void drawPoints(const float* points, int floatCount, const SkPaint& paint) override;
virtual void drawLine(float startX, float startY, float stopX, float stopY,
- const SkPaint& paint) override {
- float points[4] = { startX, startY, stopX, stopY };
+ const SkPaint& paint) override {
+ float points[4] = {startX, startY, stopX, stopY};
drawLines(points, 4, paint);
}
virtual void drawLines(const float* points, int floatCount, const SkPaint& paint) override;
- virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
+ virtual void drawRect(float left, float top, float right, float bottom,
+ const SkPaint& paint) override;
virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override;
- virtual void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) override;
+ virtual void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+ const SkPaint& paint) override;
virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
- virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint) override;
- virtual void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override;
+ virtual void drawOval(float left, float top, float right, float bottom,
+ const SkPaint& paint) override;
+ virtual void drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, bool useCenter, const SkPaint& paint) override;
virtual void drawPath(const SkPath& path, const SkPaint& paint) override;
- virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint& paint) override
- { /* RecordingCanvas does not support drawVertices(); ignore */ }
+ virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint& paint)
+ override { /* RecordingCanvas does not support drawVertices(); ignore */
+ }
virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
// Bitmap-based
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override;
- virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) override;
+ virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) override;
virtual void drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) override;
- virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkPaint* paint) override;
+ const float* vertices, const int* colors,
+ const SkPaint* paint) override;
+ virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk, float dstLeft,
+ float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) override;
+ virtual double drawAnimatedImage(AnimatedImageDrawable*) override;
// Text
virtual bool drawTextAbsolutePos() const override { return false; }
protected:
virtual void drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& paint, float x,
- float y, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
- float totalAdvance) override;
+ float y, float boundsLeft, float boundsTop, float boundsRight,
+ float boundsBottom, float totalAdvance) override;
virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
- const SkPaint& paint, const SkPath& path, size_t start, size_t end) override;
+ const SkPaint& paint, const SkPath& path, size_t start,
+ size_t end) override;
private:
const ClipBase* getRecordedClip() {
@@ -203,20 +204,19 @@ private:
void drawBitmap(Bitmap& bitmap, const SkPaint* paint);
void drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint);
-
int addOp(RecordedOp* op);
-// ----------------------------------------------------------------------------
-// lazy object copy
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // lazy object copy
+ // ----------------------------------------------------------------------------
LinearAllocator& alloc() { return mDisplayList->allocator; }
void refBitmapsInShader(const SkShader* shader);
- template<class T>
+ template <class T>
inline const T* refBuffer(const T* srcBuffer, int32_t count) {
if (!srcBuffer) return nullptr;
- T* dstBuffer = (T*) mDisplayList->allocator.alloc<T>(count * sizeof(T));
+ T* dstBuffer = (T*)mDisplayList->allocator.alloc<T>(count * sizeof(T));
memcpy(dstBuffer, srcBuffer, count * sizeof(T));
return dstBuffer;
}
@@ -311,11 +311,10 @@ private:
DeferredBarrierType mDeferredBarrierType = DeferredBarrierType::None;
const ClipBase* mDeferredBarrierClip = nullptr;
DisplayList* mDisplayList = nullptr;
- bool mHighContrastText = false;
sk_sp<SkDrawFilter> mDrawFilter;
-}; // class RecordingCanvas
+}; // class RecordingCanvas
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_RECORDING_CANVAS_H
+#endif // ANDROID_HWUI_RECORDING_CANVAS_H
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index eb05e9171335..0715187e19ea 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -20,20 +20,18 @@
#include <utils/Log.h>
+#include <SkRect.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <ostream>
-#include <SkRect.h>
namespace android {
namespace uirenderer {
#define RECT_STRING "%5.2f %5.2f %5.2f %5.2f"
-#define RECT_ARGS(r) \
- (r).left, (r).top, (r).right, (r).bottom
-#define SK_RECT_ARGS(r) \
- (r).left(), (r).top(), (r).right(), (r).bottom()
+#define RECT_ARGS(r) (r).left, (r).top, (r).right, (r).bottom
+#define SK_RECT_ARGS(r) (r).left(), (r).top(), (r).right(), (r).bottom()
///////////////////////////////////////////////////////////////////////////////
// Structs
@@ -52,52 +50,32 @@ public:
// we don't provide copy-ctor and operator= on purpose
// because we want the compiler generated versions
- inline Rect():
- left(0),
- top(0),
- right(0),
- bottom(0) {
- }
+ inline Rect() : left(0), top(0), right(0), bottom(0) {}
- inline Rect(float left, float top, float right, float bottom):
- left(left),
- top(top),
- right(right),
- bottom(bottom) {
- }
+ inline Rect(float left, float top, float right, float bottom)
+ : left(left), top(top), right(right), bottom(bottom) {}
- inline Rect(float width, float height):
- left(0.0f),
- top(0.0f),
- right(width),
- bottom(height) {
- }
+ inline Rect(float width, float height) : left(0.0f), top(0.0f), right(width), bottom(height) {}
- inline Rect(const SkIRect& rect): // NOLINT, implicit
- left(rect.fLeft),
- top(rect.fTop),
- right(rect.fRight),
- bottom(rect.fBottom) {
- }
+ inline Rect(const SkIRect& rect)
+ : // NOLINT, implicit
+ left(rect.fLeft)
+ , top(rect.fTop)
+ , right(rect.fRight)
+ , bottom(rect.fBottom) {}
- inline Rect(const SkRect& rect): // NOLINT, implicit
- left(rect.fLeft),
- top(rect.fTop),
- right(rect.fRight),
- bottom(rect.fBottom) {
- }
+ inline Rect(const SkRect& rect)
+ : // NOLINT, implicit
+ left(rect.fLeft)
+ , top(rect.fTop)
+ , right(rect.fRight)
+ , bottom(rect.fBottom) {}
- friend int operator==(const Rect& a, const Rect& b) {
- return !memcmp(&a, &b, sizeof(a));
- }
+ friend int operator==(const Rect& a, const Rect& b) { return !memcmp(&a, &b, sizeof(a)); }
- friend int operator!=(const Rect& a, const Rect& b) {
- return memcmp(&a, &b, sizeof(a));
- }
+ friend int operator!=(const Rect& a, const Rect& b) { return memcmp(&a, &b, sizeof(a)); }
- inline void clear() {
- left = top = right = bottom = 0.0f;
- }
+ inline void clear() { left = top = right = bottom = 0.0f; }
inline bool isEmpty() const {
// this is written in such way this it'll handle NANs to return
@@ -105,9 +83,7 @@ public:
return !((left < right) && (top < bottom));
}
- inline void setEmpty() {
- left = top = right = bottom = 0.0f;
- }
+ inline void setEmpty() { left = top = right = bottom = 0.0f; }
inline void set(float left, float top, float right, float bottom) {
this->left = left;
@@ -116,21 +92,13 @@ public:
this->bottom = bottom;
}
- inline void set(const Rect& r) {
- set(r.left, r.top, r.right, r.bottom);
- }
+ inline void set(const Rect& r) { set(r.left, r.top, r.right, r.bottom); }
- inline void set(const SkIRect& r) {
- set(r.left(), r.top(), r.right(), r.bottom());
- }
+ inline void set(const SkIRect& r) { set(r.left(), r.top(), r.right(), r.bottom()); }
- inline float getWidth() const {
- return right - left;
- }
+ inline float getWidth() const { return right - left; }
- inline float getHeight() const {
- return bottom - top;
- }
+ inline float getHeight() const { return bottom - top; }
bool intersects(float l, float t, float r, float b) const {
float tempLeft = std::max(left, l);
@@ -138,12 +106,10 @@ public:
float tempRight = std::min(right, r);
float tempBottom = std::min(bottom, b);
- return ((tempLeft < tempRight) && (tempTop < tempBottom)); // !isEmpty
+ return ((tempLeft < tempRight) && (tempTop < tempBottom)); // !isEmpty
}
- bool intersects(const Rect& r) const {
- return intersects(r.left, r.top, r.right, r.bottom);
- }
+ bool intersects(const Rect& r) const { return intersects(r.left, r.top, r.right, r.bottom); }
/**
* This method is named 'doIntersect' instead of 'intersect' so as not to be confused with
@@ -157,17 +123,13 @@ public:
bottom = std::min(bottom, b);
}
- void doIntersect(const Rect& r) {
- doIntersect(r.left, r.top, r.right, r.bottom);
- }
+ void doIntersect(const Rect& r) { doIntersect(r.left, r.top, r.right, r.bottom); }
inline bool contains(float l, float t, float r, float b) const {
return l >= left && t >= top && r <= right && b <= bottom;
}
- inline bool contains(const Rect& r) const {
- return contains(r.left, r.top, r.right, r.bottom);
- }
+ inline bool contains(const Rect& r) const { return contains(r.left, r.top, r.right, r.bottom); }
bool unionWith(const Rect& r) {
if (r.left < r.right && r.top < r.bottom) {
@@ -195,9 +157,7 @@ public:
bottom += dy;
}
- void inset(float delta) {
- outset(-delta);
- }
+ void inset(float delta) { outset(-delta); }
void outset(float delta) {
left -= delta;
@@ -279,13 +239,9 @@ public:
bottom = std::max(bottom, y);
}
- SkRect toSkRect() const {
- return SkRect::MakeLTRB(left, top, right, bottom);
- }
+ SkRect toSkRect() const { return SkRect::MakeLTRB(left, top, right, bottom); }
- SkIRect toSkIRect() const {
- return SkIRect::MakeLTRB(left, top, right, bottom);
- }
+ SkIRect toSkIRect() const { return SkIRect::MakeLTRB(left, top, right, bottom); }
void dump(const char* label = nullptr) const {
ALOGD("%s[l=%.2f t=%.2f r=%.2f b=%.2f]", label ? label : "Rect", left, top, right, bottom);
@@ -301,13 +257,10 @@ public:
return os << "[" << rect.right << " x " << rect.bottom << "]";
}
- return os << "[" << rect.left
- << " " << rect.top
- << " " << rect.right
- << " " << rect.bottom << "]";
+ return os << "[" << rect.left << " " << rect.top << " " << rect.right << " " << rect.bottom
+ << "]";
}
-}; // class Rect
-
-}; // namespace uirenderer
-}; // namespace android
+}; // class Rect
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/RenderBuffer.h b/libs/hwui/RenderBuffer.h
index 35a516a58022..191a66a6d741 100644
--- a/libs/hwui/RenderBuffer.h
+++ b/libs/hwui/RenderBuffer.h
@@ -32,9 +32,8 @@ struct RenderBuffer {
* Creates a new render buffer in the specified format and dimensions.
* The format must be one of the formats allowed by glRenderbufferStorage().
*/
- RenderBuffer(GLenum format, uint32_t width, uint32_t height):
- mFormat(format), mWidth(width), mHeight(height), mAllocated(false) {
-
+ RenderBuffer(GLenum format, uint32_t width, uint32_t height)
+ : mFormat(format), mWidth(width), mHeight(height), mAllocated(false) {
glGenRenderbuffers(1, &mName);
}
@@ -47,31 +46,23 @@ struct RenderBuffer {
/**
* Returns the GL name of this render buffer.
*/
- GLuint getName() const {
- return mName;
- }
+ GLuint getName() const { return mName; }
/**
* Returns the format of this render buffer.
*/
- GLenum getFormat() const {
- return mFormat;
- }
+ GLenum getFormat() const { return mFormat; }
/**
* Binds this render buffer to the current GL context.
*/
- void bind() const {
- glBindRenderbuffer(GL_RENDERBUFFER, mName);
- }
+ void bind() const { glBindRenderbuffer(GL_RENDERBUFFER, mName); }
/**
* Indicates whether this render buffer has allocated its
* storage. See allocate() and resize().
*/
- bool isAllocated() const {
- return mAllocated;
- }
+ bool isAllocated() const { return mAllocated; }
/**
* Allocates this render buffer's storage if needed.
@@ -101,23 +92,19 @@ struct RenderBuffer {
/**
* Returns the width of the render buffer in pixels.
*/
- uint32_t getWidth() const {
- return mWidth;
- }
+ uint32_t getWidth() const { return mWidth; }
/**
* Returns the height of the render buffer in pixels.
*/
- uint32_t getHeight() const {
- return mHeight;
- }
+ uint32_t getHeight() const { return mHeight; }
/**
* Returns the size of this render buffer in bytes.
*/
uint32_t getSize() const {
// Round to the nearest byte
- return (uint32_t) ((mWidth * mHeight * formatSize(mFormat)) / 8.0f + 0.5f);
+ return (uint32_t)((mWidth * mHeight * formatSize(mFormat)) / 8.0f + 0.5f);
}
/**
@@ -186,9 +173,9 @@ private:
bool mAllocated;
GLuint mName;
-}; // struct RenderBuffer
+}; // struct RenderBuffer
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_RENDER_BUFFER_H
+#endif // ANDROID_HWUI_RENDER_BUFFER_H
diff --git a/libs/hwui/RenderBufferCache.cpp b/libs/hwui/RenderBufferCache.cpp
index 2f8ddfe6d660..98010d8da1bd 100644
--- a/libs/hwui/RenderBufferCache.cpp
+++ b/libs/hwui/RenderBufferCache.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "Debug.h"
-#include "Properties.h"
#include "RenderBufferCache.h"
+#include "Debug.h"
#include "DeviceInfo.h"
+#include "Properties.h"
#include <utils/Log.h>
@@ -32,9 +32,9 @@ namespace uirenderer {
// Debug
#if DEBUG_RENDER_BUFFERS
- #define RENDER_BUFFER_LOGD(...) ALOGD(__VA_ARGS__)
+#define RENDER_BUFFER_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define RENDER_BUFFER_LOGD(...)
+#define RENDER_BUFFER_LOGD(...)
#endif
static uint32_t calculateRboCacheSize() {
@@ -48,9 +48,7 @@ static uint32_t calculateRboCacheSize() {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-RenderBufferCache::RenderBufferCache()
- : mSize(0)
- , mMaxSize(calculateRboCacheSize()) {}
+RenderBufferCache::RenderBufferCache() : mSize(0), mMaxSize(calculateRboCacheSize()) {}
RenderBufferCache::~RenderBufferCache() {
clear();
@@ -72,9 +70,8 @@ uint32_t RenderBufferCache::getMaxSize() {
// Caching
///////////////////////////////////////////////////////////////////////////////
-int RenderBufferCache::RenderBufferEntry::compare(
- const RenderBufferCache::RenderBufferEntry& lhs,
- const RenderBufferCache::RenderBufferEntry& rhs) {
+int RenderBufferCache::RenderBufferEntry::compare(const RenderBufferCache::RenderBufferEntry& lhs,
+ const RenderBufferCache::RenderBufferEntry& rhs) {
int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
if (deltaInt != 0) return deltaInt;
@@ -87,8 +84,8 @@ int RenderBufferCache::RenderBufferEntry::compare(
void RenderBufferCache::deleteBuffer(RenderBuffer* buffer) {
if (buffer) {
RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d)",
- RenderBuffer::formatName(buffer->getFormat()),
- buffer->getWidth(), buffer->getHeight());
+ RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
+ buffer->getHeight());
mSize -= buffer->getSize();
delete buffer;
@@ -115,13 +112,13 @@ RenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const
buffer = entry.mBuffer;
mSize -= buffer->getSize();
- RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)",
- RenderBuffer::formatName(format), width, height);
+ RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)", RenderBuffer::formatName(format),
+ width, height);
} else {
buffer = new RenderBuffer(format, width, height);
- RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)",
- RenderBuffer::formatName(format), width, height);
+ RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)", RenderBuffer::formatName(format),
+ width, height);
}
buffer->bind();
@@ -147,18 +144,18 @@ bool RenderBufferCache::put(RenderBuffer* buffer) {
mSize += size;
RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
- RenderBuffer::formatName(buffer->getFormat()),
- buffer->getWidth(), buffer->getHeight());
+ RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
+ buffer->getHeight());
return true;
} else {
RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d) Size=%d, MaxSize=%d",
- RenderBuffer::formatName(buffer->getFormat()),
- buffer->getWidth(), buffer->getHeight(), size, mMaxSize);
+ RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
+ buffer->getHeight(), size, mMaxSize);
delete buffer;
}
return false;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/RenderBufferCache.h b/libs/hwui/RenderBufferCache.h
index 644433145cd0..c936a5283965 100644
--- a/libs/hwui/RenderBufferCache.h
+++ b/libs/hwui/RenderBufferCache.h
@@ -74,28 +74,22 @@ public:
private:
struct RenderBufferEntry {
- RenderBufferEntry():
- mBuffer(nullptr), mWidth(0), mHeight(0) {
- }
+ RenderBufferEntry() : mBuffer(nullptr), mWidth(0), mHeight(0) {}
- RenderBufferEntry(GLenum format, const uint32_t width, const uint32_t height):
- mBuffer(nullptr), mFormat(format), mWidth(width), mHeight(height) {
- }
+ RenderBufferEntry(GLenum format, const uint32_t width, const uint32_t height)
+ : mBuffer(nullptr), mFormat(format), mWidth(width), mHeight(height) {}
- explicit RenderBufferEntry(RenderBuffer* buffer):
- mBuffer(buffer), mFormat(buffer->getFormat()),
- mWidth(buffer->getWidth()), mHeight(buffer->getHeight()) {
- }
+ explicit RenderBufferEntry(RenderBuffer* buffer)
+ : mBuffer(buffer)
+ , mFormat(buffer->getFormat())
+ , mWidth(buffer->getWidth())
+ , mHeight(buffer->getHeight()) {}
static int compare(const RenderBufferEntry& lhs, const RenderBufferEntry& rhs);
- bool operator==(const RenderBufferEntry& other) const {
- return compare(*this, other) == 0;
- }
+ bool operator==(const RenderBufferEntry& other) const { return compare(*this, other) == 0; }
- bool operator!=(const RenderBufferEntry& other) const {
- return compare(*this, other) != 0;
- }
+ bool operator!=(const RenderBufferEntry& other) const { return compare(*this, other) != 0; }
bool operator<(const RenderBufferEntry& other) const {
return RenderBufferEntry::compare(*this, other) < 0;
@@ -105,7 +99,7 @@ private:
GLenum mFormat;
uint32_t mWidth;
uint32_t mHeight;
- }; // struct RenderBufferEntry
+ }; // struct RenderBufferEntry
void deleteBuffer(RenderBuffer* buffer);
@@ -113,9 +107,9 @@ private:
uint32_t mSize;
uint32_t mMaxSize;
-}; // class RenderBufferCache
+}; // class RenderBufferCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_RENDER_BUFFER_CACHE_H
+#endif // ANDROID_HWUI_RENDER_BUFFER_CACHE_H
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 61b3876cd095..d93a7578cfd7 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -21,17 +21,18 @@
#include "Debug.h"
#include "RecordedOp.h"
#include "TreeInfo.h"
+#include "VectorDrawable.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/CanvasContext.h"
#include "utils/FatVector.h"
#include "utils/MathUtils.h"
#include "utils/StringUtils.h"
#include "utils/TraceUtils.h"
-#include "VectorDrawable.h"
-#include "renderstate/RenderState.h"
-#include "renderthread/CanvasContext.h"
-#include "protos/hwui.pb.h"
#include "protos/ProtoHelpers.h"
+#include "protos/hwui.pb.h"
+#include <SkPathOps.h>
#include <algorithm>
#include <sstream>
#include <string>
@@ -45,9 +46,7 @@ class ImmediateRemoved : public TreeObserver {
public:
explicit ImmediateRemoved(TreeInfo* info) : mTreeInfo(info) {}
- void onMaybeRemovedFromTree(RenderNode* node) override {
- node->onRemovedFromTree(mTreeInfo);
- }
+ void onMaybeRemovedFromTree(RenderNode* node) override { node->onRemovedFromTree(mTreeInfo); }
private:
TreeInfo* mTreeInfo;
@@ -59,8 +58,7 @@ RenderNode::RenderNode()
, mDisplayList(nullptr)
, mStagingDisplayList(nullptr)
, mAnimatorManager(*this)
- , mParentCount(0) {
-}
+ , mParentCount(0) {}
RenderNode::~RenderNode() {
ImmediateRemoved observer(nullptr);
@@ -88,12 +86,11 @@ void RenderNode::output() {
void RenderNode::output(std::ostream& output, uint32_t level) {
output << " (" << getName() << " " << this
- << (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : "")
- << (properties().hasShadow() ? ", casting shadow" : "")
- << (isRenderable() ? "" : ", empty")
- << (properties().getProjectBackwards() ? ", projected" : "")
- << (hasLayer() ? ", on HW Layer" : "")
- << ")" << std::endl;
+ << (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : "")
+ << (properties().hasShadow() ? ", casting shadow" : "")
+ << (isRenderable() ? "" : ", empty")
+ << (properties().getProjectBackwards() ? ", projected" : "")
+ << (hasLayer() ? ", on HW Layer" : "") << ")" << std::endl;
properties().debugOutputProperties(output, level + 1);
@@ -104,9 +101,8 @@ void RenderNode::output(std::ostream& output, uint32_t level) {
output << std::endl;
}
-void RenderNode::copyTo(proto::RenderNode *pnode) {
- pnode->set_id(static_cast<uint64_t>(
- reinterpret_cast<uintptr_t>(this)));
+void RenderNode::copyTo(proto::RenderNode* pnode) {
+ pnode->set_id(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this)));
pnode->set_name(mName.string(), mName.length());
proto::RenderProperties* pprops = pnode->mutable_properties();
@@ -238,35 +234,20 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
LayerType layerType = properties().effectiveLayerType();
// If we are not a layer OR we cannot be rendered (eg, view was detached)
// we need to destroy any Layers we may have had previously
- if (CC_LIKELY(layerType != LayerType::RenderLayer)
- || CC_UNLIKELY(!isRenderable())
- || CC_UNLIKELY(properties().getWidth() == 0)
- || CC_UNLIKELY(properties().getHeight() == 0)
- || CC_UNLIKELY(!properties().fitsOnLayer())) {
+ if (CC_LIKELY(layerType != LayerType::RenderLayer) || CC_UNLIKELY(!isRenderable()) ||
+ CC_UNLIKELY(properties().getWidth() == 0) || CC_UNLIKELY(properties().getHeight() == 0) ||
+ CC_UNLIKELY(!properties().fitsOnLayer())) {
if (CC_UNLIKELY(hasLayer())) {
renderthread::CanvasContext::destroyLayer(this);
}
return;
}
- if(info.canvasContext.createOrUpdateLayer(this, *info.damageAccumulator)) {
+ if (info.canvasContext.createOrUpdateLayer(this, *info.damageAccumulator, info.errorHandler)) {
damageSelf(info);
}
if (!hasLayer()) {
- Caches::getInstance().dumpMemoryUsage();
- if (info.errorHandler) {
- std::ostringstream err;
- err << "Unable to create layer for " << getName();
- const int maxTextureSize = Caches::getInstance().maxTextureSize;
- if (getWidth() > maxTextureSize || getHeight() > maxTextureSize) {
- err << ", size " << getWidth() << "x" << getHeight()
- << " exceeds max size " << maxTextureSize;
- } else {
- err << ", see logcat for more info";
- }
- info.errorHandler->onError(err.str());
- }
return;
}
@@ -305,8 +286,8 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu
} else if (mDisplayList) {
willHaveFunctor = mDisplayList->hasFunctor();
}
- bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
- willHaveFunctor, functorsNeedLayer);
+ bool childFunctorsNeedLayer =
+ mProperties.prepareForFunctorPresence(willHaveFunctor, functorsNeedLayer);
if (CC_UNLIKELY(mPositionListener.get())) {
mPositionListener->onPositionUpdated(*this, info);
@@ -319,10 +300,12 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu
if (mDisplayList) {
info.out.hasFunctors |= mDisplayList->hasFunctor();
- bool isDirty = mDisplayList->prepareListAndChildren(observer, info, childFunctorsNeedLayer,
- [](RenderNode* child, TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) {
- child->prepareTreeImpl(observer, info, functorsNeedLayer);
- });
+ bool isDirty = mDisplayList->prepareListAndChildren(
+ observer, info, childFunctorsNeedLayer,
+ [](RenderNode* child, TreeObserver& observer, TreeInfo& info,
+ bool functorsNeedLayer) {
+ child->prepareTreeImpl(observer, info, functorsNeedLayer);
+ });
if (isDirty) {
damageSelf(info);
}
@@ -362,9 +345,7 @@ void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) {
// Make sure we inc first so that we don't fluctuate between 0 and 1,
// which would thrash the layer cache
if (mStagingDisplayList) {
- mStagingDisplayList->updateChildren([](RenderNode* child) {
- child->incParentRefCount();
- });
+ mStagingDisplayList->updateChildren([](RenderNode* child) { child->incParentRefCount(); });
}
deleteDisplayList(observer, info);
mDisplayList = mStagingDisplayList;
@@ -387,9 +368,8 @@ void RenderNode::pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo&
void RenderNode::deleteDisplayList(TreeObserver& observer, TreeInfo* info) {
if (mDisplayList) {
- mDisplayList->updateChildren([&observer, info](RenderNode* child) {
- child->decParentRefCount(observer, info);
- });
+ mDisplayList->updateChildren(
+ [&observer, info](RenderNode* child) { child->decParentRefCount(observer, info); });
if (!mDisplayList->reuseDisplayList(this, info ? &info->canvasContext : nullptr)) {
delete mDisplayList;
}
@@ -412,9 +392,7 @@ void RenderNode::destroyLayers() {
renderthread::CanvasContext::destroyLayer(this);
}
if (mDisplayList) {
- mDisplayList->updateChildren([](RenderNode* child) {
- child->destroyLayers();
- });
+ mDisplayList->updateChildren([](RenderNode* child) { child->destroyLayers(); });
}
}
@@ -460,16 +438,15 @@ void RenderNode::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform)
if (properties().hasTransformMatrix() || applyTranslationZ) {
if (properties().isTransformTranslateOnly()) {
matrix.translate(properties().getTranslationX(), properties().getTranslationY(),
- true3dTransform ? properties().getZ() : 0.0f);
+ true3dTransform ? properties().getZ() : 0.0f);
} else {
if (!true3dTransform) {
matrix.multiply(*properties().getTransformMatrix());
} else {
mat4 true3dMat;
- true3dMat.loadTranslate(
- properties().getPivotX() + properties().getTranslationX(),
- properties().getPivotY() + properties().getTranslationY(),
- properties().getZ());
+ true3dMat.loadTranslate(properties().getPivotX() + properties().getTranslationX(),
+ properties().getPivotY() + properties().getTranslationY(),
+ properties().getZ());
true3dMat.rotate(properties().getRotationX(), 1, 0, 0);
true3dMat.rotate(properties().getRotationY(), 0, 1, 0);
true3dMat.rotate(properties().getRotation(), 0, 0, 1);
@@ -504,8 +481,7 @@ void RenderNode::computeOrdering() {
}
void RenderNode::computeOrderingImpl(
- RenderNodeOp* opState,
- std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
+ RenderNodeOp* opState, std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
const mat4* transformFromProjectionSurface) {
mProjectedNodes.clear();
if (mDisplayList == nullptr || mDisplayList->isEmpty()) return;
@@ -555,5 +531,22 @@ void RenderNode::computeOrderingImpl(
}
}
+const SkPath* RenderNode::getClippedOutline(const SkRect& clipRect) const {
+ const SkPath* outlinePath = properties().getOutline().getPath();
+ const uint32_t outlineID = outlinePath->getGenerationID();
+
+ if (outlineID != mClippedOutlineCache.outlineID || clipRect != mClippedOutlineCache.clipRect) {
+ // update the cache keys
+ mClippedOutlineCache.outlineID = outlineID;
+ mClippedOutlineCache.clipRect = clipRect;
+
+ // update the cache value by recomputing a new path
+ SkPath clipPath;
+ clipPath.addRect(clipRect);
+ Op(*outlinePath, clipPath, kIntersect_SkPathOp, &mClippedOutlineCache.clippedOutline);
+ }
+ return &mClippedOutlineCache.clippedOutline;
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index c4ae82af430c..1469a156e2d8 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -63,7 +63,8 @@ class RenderNode;
}
/**
- * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
+ * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display
+ * properties.
*
* Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
* functionality is split between RecordingCanvas (which manages the recording), DisplayList
@@ -74,33 +75,32 @@ class RenderNode;
* attached.
*/
class RenderNode : public VirtualLightRefBase {
-friend class TestUtils; // allow TestUtils to access syncDisplayList / syncProperties
-friend class FrameBuilder;
+ friend class TestUtils; // allow TestUtils to access syncDisplayList / syncProperties
+ friend class FrameBuilder;
+
public:
enum DirtyPropertyMask {
- GENERIC = 1 << 1,
- TRANSLATION_X = 1 << 2,
- TRANSLATION_Y = 1 << 3,
- TRANSLATION_Z = 1 << 4,
- SCALE_X = 1 << 5,
- SCALE_Y = 1 << 6,
- ROTATION = 1 << 7,
- ROTATION_X = 1 << 8,
- ROTATION_Y = 1 << 9,
- X = 1 << 10,
- Y = 1 << 11,
- Z = 1 << 12,
- ALPHA = 1 << 13,
- DISPLAY_LIST = 1 << 14,
+ GENERIC = 1 << 1,
+ TRANSLATION_X = 1 << 2,
+ TRANSLATION_Y = 1 << 3,
+ TRANSLATION_Z = 1 << 4,
+ SCALE_X = 1 << 5,
+ SCALE_Y = 1 << 6,
+ ROTATION = 1 << 7,
+ ROTATION_X = 1 << 8,
+ ROTATION_Y = 1 << 9,
+ X = 1 << 10,
+ Y = 1 << 11,
+ Z = 1 << 12,
+ ALPHA = 1 << 13,
+ DISPLAY_LIST = 1 << 14,
};
ANDROID_API RenderNode();
ANDROID_API virtual ~RenderNode();
// See flags defined in DisplayList.java
- enum ReplayFlag {
- kReplayFlag_ClipChildren = 0x1
- };
+ enum ReplayFlag { kReplayFlag_ClipChildren = 0x1 };
ANDROID_API void setStagingDisplayList(DisplayList* newData);
@@ -110,17 +110,13 @@ public:
ANDROID_API int getDebugSize();
void copyTo(proto::RenderNode* node);
- bool isRenderable() const {
- return mDisplayList && !mDisplayList->isEmpty();
- }
+ bool isRenderable() const { return mDisplayList && !mDisplayList->isEmpty(); }
bool hasProjectionReceiver() const {
return mDisplayList && mDisplayList->projectionReceiveIndex >= 0;
}
- const char* getName() const {
- return mName.string();
- }
+ const char* getName() const { return mName.string(); }
void setName(const char* name) {
if (name) {
@@ -133,49 +129,29 @@ public:
}
}
- VirtualLightRefBase* getUserContext() const {
- return mUserContext.get();
- }
+ VirtualLightRefBase* getUserContext() const { return mUserContext.get(); }
- void setUserContext(VirtualLightRefBase* context) {
- mUserContext = context;
- }
+ void setUserContext(VirtualLightRefBase* context) { mUserContext = context; }
bool isPropertyFieldDirty(DirtyPropertyMask field) const {
return mDirtyPropertyFields & field;
}
- void setPropertyFieldsDirty(uint32_t fields) {
- mDirtyPropertyFields |= fields;
- }
+ void setPropertyFieldsDirty(uint32_t fields) { mDirtyPropertyFields |= fields; }
- const RenderProperties& properties() const {
- return mProperties;
- }
+ const RenderProperties& properties() const { return mProperties; }
- RenderProperties& animatorProperties() {
- return mProperties;
- }
+ RenderProperties& animatorProperties() { return mProperties; }
- const RenderProperties& stagingProperties() {
- return mStagingProperties;
- }
+ const RenderProperties& stagingProperties() { return mStagingProperties; }
- RenderProperties& mutateStagingProperties() {
- return mStagingProperties;
- }
+ RenderProperties& mutateStagingProperties() { return mStagingProperties; }
- bool isValid() {
- return mValid;
- }
+ bool isValid() { return mValid; }
- int getWidth() const {
- return properties().getWidth();
- }
+ int getWidth() const { return properties().getWidth(); }
- int getHeight() const {
- return properties().getHeight();
- }
+ int getHeight() const { return properties().getHeight(); }
ANDROID_API virtual void prepareTree(TreeInfo& info);
void destroyHardwareResources(TreeInfo* info = nullptr);
@@ -196,18 +172,14 @@ public:
bool nothingToDraw() const {
const Outline& outline = properties().getOutline();
- return mDisplayList == nullptr
- || properties().getAlpha() <= 0
- || (outline.getShouldClip() && outline.isEmpty())
- || properties().getScaleX() == 0
- || properties().getScaleY() == 0;
+ return mDisplayList == nullptr || properties().getAlpha() <= 0 ||
+ (outline.getShouldClip() && outline.isEmpty()) || properties().getScaleX() == 0 ||
+ properties().getScaleY() == 0;
}
- const DisplayList* getDisplayList() const {
- return mDisplayList;
- }
+ const DisplayList* getDisplayList() const { return mDisplayList; }
OffscreenBuffer* getLayer() const { return mLayer; }
- OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
+ OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
void setLayer(OffscreenBuffer* layer) { mLayer = layer; }
// Note: The position callbacks are relying on the listener using
@@ -234,16 +206,12 @@ public:
// This is only modified in MODE_FULL, so it can be safely accessed
// on the UI thread.
- ANDROID_API bool hasParents() {
- return mParentCount;
- }
+ ANDROID_API bool hasParents() { return mParentCount; }
void onRemovedFromTree(TreeInfo* info);
// Called by CanvasContext to promote a RenderNode to be a root node
- void makeRoot() {
- incParentRefCount();
- }
+ void makeRoot() { incParentRefCount(); }
// Called by CanvasContext when it drops a RenderNode from being a root node
void clearRoot();
@@ -252,8 +220,8 @@ public:
private:
void computeOrderingImpl(RenderNodeOp* opState,
- std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
- const mat4* transformFromProjectionSurface);
+ std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
+ const mat4* transformFromProjectionSurface);
void syncProperties();
void syncDisplayList(TreeObserver& observer, TreeInfo* info);
@@ -309,7 +277,7 @@ private:
sp<PositionListener> mPositionListener;
-// METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
+ // METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
public:
/**
* Detach and transfer ownership of an already allocated displayList for use
@@ -361,9 +329,19 @@ public:
return mSkiaLayer.get() ? mSkiaLayer->layerSurface.get() : nullptr;
}
- skiapipeline::SkiaLayer* getSkiaLayer() const {
- return mSkiaLayer.get();
- }
+ skiapipeline::SkiaLayer* getSkiaLayer() const { return mSkiaLayer.get(); }
+
+ /**
+ * Returns the path that represents the outline of RenderNode intersected with
+ * the provided rect. This call will internally cache the resulting path in
+ * order to potentially return that path for subsequent calls to this method.
+ * By reusing the same path we get better performance on the GPU backends since
+ * those resources are cached in the hardware based on the path's genID.
+ *
+ * The returned path is only guaranteed to be valid until this function is called
+ * again or the RenderNode's outline is mutated.
+ */
+ const SkPath* getClippedOutline(const SkRect& clipRect) const;
private:
/**
@@ -380,17 +358,25 @@ private:
* when it has been set to draw as a LayerType::RenderLayer.
*/
std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
-}; // class RenderNode
+
+ struct ClippedOutlineCache {
+ // keys
+ uint32_t outlineID = 0;
+ SkRect clipRect;
+
+ // value
+ SkPath clippedOutline;
+ };
+ mutable ClippedOutlineCache mClippedOutlineCache;
+}; // class RenderNode
class MarkAndSweepRemoved : public TreeObserver {
-PREVENT_COPY_AND_ASSIGN(MarkAndSweepRemoved);
+ PREVENT_COPY_AND_ASSIGN(MarkAndSweepRemoved);
public:
explicit MarkAndSweepRemoved(TreeInfo* info) : mTreeInfo(info) {}
- void onMaybeRemovedFromTree(RenderNode* node) override {
- mMarked.emplace_back(node);
- }
+ void onMaybeRemovedFromTree(RenderNode* node) override { mMarked.emplace_back(node); }
~MarkAndSweepRemoved() {
for (auto& node : mMarked) {
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 146fbe73a48a..e49574462e9e 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -44,9 +44,9 @@ void LayerProperties::reset() {
}
bool LayerProperties::setColorFilter(SkColorFilter* filter) {
- if (mColorFilter == filter) return false;
- SkRefCnt_SafeAssign(mColorFilter, filter);
- return true;
+ if (mColorFilter == filter) return false;
+ SkRefCnt_SafeAssign(mColorFilter, filter);
+ return true;
}
bool LayerProperties::setFromPaint(const SkPaint* paint) {
@@ -66,18 +66,13 @@ LayerProperties& LayerProperties::operator=(const LayerProperties& other) {
return *this;
}
-RenderProperties::ComputedFields::ComputedFields()
- : mTransformMatrix(nullptr) {
-}
+RenderProperties::ComputedFields::ComputedFields() : mTransformMatrix(nullptr) {}
RenderProperties::ComputedFields::~ComputedFields() {
delete mTransformMatrix;
}
-RenderProperties::RenderProperties()
- : mStaticMatrix(nullptr)
- , mAnimationMatrix(nullptr) {
-}
+RenderProperties::RenderProperties() : mStaticMatrix(nullptr), mAnimationMatrix(nullptr) {}
RenderProperties::~RenderProperties() {
delete mStaticMatrix;
@@ -99,14 +94,14 @@ RenderProperties& RenderProperties::operator=(const RenderProperties& other) {
return *this;
}
-static void dumpMatrix(std::ostream& output, std::string& indent,
- const char* label, SkMatrix* matrix) {
- if (matrix) {
- output << indent << "(" << label << " " << matrix << ": ";
+static void dumpMatrix(std::ostream& output, std::string& indent, const char* label,
+ SkMatrix* matrix) {
+ if (matrix) {
+ output << indent << "(" << label << " " << matrix << ": ";
output << std::fixed << std::setprecision(2);
- output << "[" << matrix->get(0) << " "<< matrix->get(1) << " " << matrix->get(2) << "]";
- output << " [" << matrix->get(3) << " "<< matrix->get(4) << " " << matrix->get(5) << "]";
- output << " [" << matrix->get(6) << " "<< matrix->get(7) << " " << matrix->get(8) << "]";
+ output << "[" << matrix->get(0) << " " << matrix->get(1) << " " << matrix->get(2) << "]";
+ output << " [" << matrix->get(3) << " " << matrix->get(4) << " " << matrix->get(5) << "]";
+ output << " [" << matrix->get(6) << " " << matrix->get(7) << " " << matrix->get(8) << "]";
output << ")" << std::endl;
}
}
@@ -114,8 +109,8 @@ static void dumpMatrix(std::ostream& output, std::string& indent,
void RenderProperties::debugOutputProperties(std::ostream& output, const int level) const {
auto indent = std::string(level * 2, ' ');
if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) {
- output << indent << "(Translate (left, top) " << mPrimitiveFields.mLeft
- << ", " << mPrimitiveFields.mTop << ")" << std::endl;
+ output << indent << "(Translate (left, top) " << mPrimitiveFields.mLeft << ", "
+ << mPrimitiveFields.mTop << ")" << std::endl;
}
dumpMatrix(output, indent, "ConcatMatrix (static)", mStaticMatrix);
dumpMatrix(output, indent, "ConcatMatrix (animation)", mAnimationMatrix);
@@ -124,7 +119,7 @@ void RenderProperties::debugOutputProperties(std::ostream& output, const int lev
if (hasTransformMatrix()) {
if (isTransformTranslateOnly()) {
output << indent << "(Translate " << getTranslationX() << ", " << getTranslationY()
- << ", " << getZ() << ")" << std::endl;
+ << ", " << getZ() << ")" << std::endl;
} else {
dumpMatrix(output, indent, "ConcatMatrix ", mComputedFields.mTransformMatrix);
}
@@ -132,10 +127,9 @@ void RenderProperties::debugOutputProperties(std::ostream& output, const int lev
const bool isLayer = effectiveLayerType() != LayerType::None;
int clipFlags = getClippingFlags();
- if (mPrimitiveFields.mAlpha < 1
- && !MathUtils::isZero(mPrimitiveFields.mAlpha)) {
+ if (mPrimitiveFields.mAlpha < 1 && !MathUtils::isZero(mPrimitiveFields.mAlpha)) {
if (isLayer) {
- clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
+ clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
}
if (CC_LIKELY(isLayer || !getHasOverlappingRendering())) {
@@ -146,31 +140,28 @@ void RenderProperties::debugOutputProperties(std::ostream& output, const int lev
Rect layerBounds(0, 0, getWidth(), getHeight());
if (clipFlags) {
getClippingRectForFlags(clipFlags, &layerBounds);
- clipFlags = 0; // all clipping done by savelayer
+ clipFlags = 0; // all clipping done by savelayer
}
- output << indent << "(SaveLayerAlpha "
- << (int)layerBounds.left << ", " << (int)layerBounds.top << ", "
- << (int)layerBounds.right << ", " << (int)layerBounds.bottom << ", "
- << (int)(mPrimitiveFields.mAlpha * 255) << ", 0x" << std::hex
- << (SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer) << ")" << std::dec
- << std::endl;
+ output << indent << "(SaveLayerAlpha " << (int)layerBounds.left << ", "
+ << (int)layerBounds.top << ", " << (int)layerBounds.right << ", "
+ << (int)layerBounds.bottom << ", " << (int)(mPrimitiveFields.mAlpha * 255)
+ << ", 0x" << std::hex << (SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer)
+ << ")" << std::dec << std::endl;
}
}
if (clipFlags) {
Rect clipRect;
getClippingRectForFlags(clipFlags, &clipRect);
- output << indent << "(ClipRect "
- << (int)clipRect.left << ", " << (int)clipRect.top << ", "
- << (int)clipRect.right << ", " << (int)clipRect.bottom << ")" << std::endl;
+ output << indent << "(ClipRect " << (int)clipRect.left << ", " << (int)clipRect.top << ", "
+ << (int)clipRect.right << ", " << (int)clipRect.bottom << ")" << std::endl;
}
if (getRevealClip().willClip()) {
Rect bounds;
getRevealClip().getBounds(&bounds);
- output << indent << "(Clip to reveal clip with bounds "
- << bounds.left << ", " << bounds.top << ", "
- << bounds.right << ", " << bounds.bottom << ")" << std::endl;
+ output << indent << "(Clip to reveal clip with bounds " << bounds.left << ", " << bounds.top
+ << ", " << bounds.right << ", " << bounds.bottom << ")" << std::endl;
}
auto& outline = mPrimitiveFields.mOutline;
@@ -179,9 +170,8 @@ void RenderProperties::debugOutputProperties(std::ostream& output, const int lev
output << indent << "(Clip to empty outline)";
} else if (outline.willClip()) {
const Rect& bounds = outline.getBounds();
- output << indent << "(Clip to outline with bounds "
- << bounds.left << ", " << bounds.top << ", "
- << bounds.right << ", " << bounds.bottom << ")" << std::endl;
+ output << indent << "(Clip to outline with bounds " << bounds.left << ", " << bounds.top
+ << ", " << bounds.right << ", " << bounds.bottom << ")" << std::endl;
}
}
}
@@ -212,7 +202,7 @@ void RenderProperties::updateMatrix() {
mComputedFields.mTransformCamera.getMatrix(&transform3D);
transform3D.preTranslate(-getPivotX(), -getPivotY());
transform3D.postTranslate(getPivotX() + getTranslationX(),
- getPivotY() + getTranslationY());
+ getPivotY() + getTranslationY());
transform->postConcat(transform3D);
mComputedFields.mTransformCamera.restore();
}
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 9ee2f9c69343..6470d4c16130 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -18,24 +18,25 @@
#include "Caches.h"
#include "DeviceInfo.h"
+#include "Outline.h"
#include "Rect.h"
#include "RevealClip.h"
-#include "Outline.h"
#include "utils/MathUtils.h"
#include "utils/PaintUtils.h"
#include <SkBlendMode.h>
#include <SkCamera.h>
+#include <SkColor.h>
#include <SkMatrix.h>
#include <SkRegion.h>
-#include <algorithm>
-#include <stddef.h>
-#include <vector>
-#include <cutils/compiler.h>
#include <androidfw/ResourceTypes.h>
+#include <cutils/compiler.h>
+#include <stddef.h>
#include <utils/Log.h>
+#include <algorithm>
#include <ostream>
+#include <vector>
class SkBitmap;
class SkColorFilter;
@@ -55,15 +56,14 @@ class RenderProperties;
// Keep in sync with View.java:LAYER_TYPE_*
enum class LayerType {
None = 0,
- // Although we cannot build the software layer directly (must be done at
- // record time), this information is used when applying alpha.
+ // We cannot build the software layer directly (must be done at record time) and all management
+ // of software layers is handled in Java.
Software = 1,
RenderLayer = 2,
- // TODO: LayerTypeSurfaceTexture? Maybe?
};
enum ClippingFlags {
- CLIP_TO_BOUNDS = 0x1 << 0,
+ CLIP_TO_BOUNDS = 0x1 << 0,
CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
};
@@ -77,43 +77,27 @@ public:
return false;
}
- bool setOpaque(bool opaque) {
- return RP_SET(mOpaque, opaque);
- }
+ bool setOpaque(bool opaque) { return RP_SET(mOpaque, opaque); }
- bool opaque() const {
- return mOpaque;
- }
+ bool opaque() const { return mOpaque; }
- bool setAlpha(uint8_t alpha) {
- return RP_SET(mAlpha, alpha);
- }
+ bool setAlpha(uint8_t alpha) { return RP_SET(mAlpha, alpha); }
- uint8_t alpha() const {
- return mAlpha;
- }
+ uint8_t alpha() const { return mAlpha; }
- bool setXferMode(SkBlendMode mode) {
- return RP_SET(mMode, mode);
- }
+ bool setXferMode(SkBlendMode mode) { return RP_SET(mMode, mode); }
- SkBlendMode xferMode() const {
- return mMode;
- }
+ SkBlendMode xferMode() const { return mMode; }
bool setColorFilter(SkColorFilter* filter);
- SkColorFilter* colorFilter() const {
- return mColorFilter;
- }
+ SkColorFilter* colorFilter() const { return mColorFilter; }
// Sets alpha, xfermode, and colorfilter from an SkPaint
// paint may be NULL, in which case defaults will be set
bool setFromPaint(const SkPaint* paint);
- bool needsBlending() const {
- return !opaque() || alpha() < 255;
- }
+ bool needsBlending() const { return !opaque() || alpha() < 255; }
LayerProperties& operator=(const LayerProperties& other);
@@ -123,9 +107,7 @@ private:
void reset();
// Private since external users should go through properties().effectiveLayerType()
- LayerType type() const {
- return mType;
- }
+ LayerType type() const { return mType; }
friend class RenderProperties;
@@ -169,16 +151,17 @@ public:
*/
bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
// parent may have already dictated that a descendant layer is needed
- bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
+ bool functorsNeedLayer =
+ ancestorDictatesFunctorsNeedLayer
// Round rect clipping forces layer for functors
- || CC_UNLIKELY(getOutline().willRoundRectClip())
- || CC_UNLIKELY(getRevealClip().willClip())
+ || CC_UNLIKELY(getOutline().willRoundRectClip()) ||
+ CC_UNLIKELY(getRevealClip().willClip())
// Complex matrices forces layer, due to stencil clipping
- || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
- || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
- || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
+ || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate()) ||
+ CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate()) ||
+ CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
@@ -210,9 +193,7 @@ public:
return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
}
- bool isProjectionReceiver() const {
- return mPrimitiveFields.mProjectionReceiver;
- }
+ bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; }
bool setStaticMatrix(const SkMatrix* matrix) {
delete mStaticMatrix;
@@ -225,9 +206,7 @@ public:
}
// Can return NULL
- const SkMatrix* getStaticMatrix() const {
- return mStaticMatrix;
- }
+ const SkMatrix* getStaticMatrix() const { return mStaticMatrix; }
bool setAnimationMatrix(const SkMatrix* matrix) {
delete mAnimationMatrix;
@@ -244,124 +223,85 @@ public:
return RP_SET(mPrimitiveFields.mAlpha, alpha);
}
- float getAlpha() const {
- return mPrimitiveFields.mAlpha;
- }
+ float getAlpha() const { return mPrimitiveFields.mAlpha; }
bool setHasOverlappingRendering(bool hasOverlappingRendering) {
return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
}
- bool hasOverlappingRendering() const {
- return mPrimitiveFields.mHasOverlappingRendering;
- }
+ bool hasOverlappingRendering() const { return mPrimitiveFields.mHasOverlappingRendering; }
bool setElevation(float elevation) {
return RP_SET(mPrimitiveFields.mElevation, elevation);
// Don't dirty matrix/pivot, since they don't respect Z
}
- float getElevation() const {
- return mPrimitiveFields.mElevation;
- }
+ float getElevation() const { return mPrimitiveFields.mElevation; }
bool setTranslationX(float translationX) {
return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
}
- float getTranslationX() const {
- return mPrimitiveFields.mTranslationX;
- }
+ float getTranslationX() const { return mPrimitiveFields.mTranslationX; }
bool setTranslationY(float translationY) {
return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
}
- float getTranslationY() const {
- return mPrimitiveFields.mTranslationY;
- }
+ float getTranslationY() const { return mPrimitiveFields.mTranslationY; }
bool setTranslationZ(float translationZ) {
return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
// mMatrixOrPivotDirty not set, since matrix doesn't respect Z
}
- float getTranslationZ() const {
- return mPrimitiveFields.mTranslationZ;
- }
+ float getTranslationZ() const { return mPrimitiveFields.mTranslationZ; }
// Animation helper
- bool setX(float value) {
- return setTranslationX(value - getLeft());
- }
+ bool setX(float value) { return setTranslationX(value - getLeft()); }
// Animation helper
- float getX() const {
- return getLeft() + getTranslationX();
- }
+ float getX() const { return getLeft() + getTranslationX(); }
// Animation helper
- bool setY(float value) {
- return setTranslationY(value - getTop());
- }
+ bool setY(float value) { return setTranslationY(value - getTop()); }
// Animation helper
- float getY() const {
- return getTop() + getTranslationY();
- }
+ float getY() const { return getTop() + getTranslationY(); }
// Animation helper
- bool setZ(float value) {
- return setTranslationZ(value - getElevation());
- }
+ bool setZ(float value) { return setTranslationZ(value - getElevation()); }
- float getZ() const {
- return getElevation() + getTranslationZ();
- }
+ float getZ() const { return getElevation() + getTranslationZ(); }
bool setRotation(float rotation) {
return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
}
- float getRotation() const {
- return mPrimitiveFields.mRotation;
- }
+ float getRotation() const { return mPrimitiveFields.mRotation; }
bool setRotationX(float rotationX) {
return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
}
- float getRotationX() const {
- return mPrimitiveFields.mRotationX;
- }
+ float getRotationX() const { return mPrimitiveFields.mRotationX; }
bool setRotationY(float rotationY) {
return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
}
- float getRotationY() const {
- return mPrimitiveFields.mRotationY;
- }
+ float getRotationY() const { return mPrimitiveFields.mRotationY; }
- bool setScaleX(float scaleX) {
- return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
- }
+ bool setScaleX(float scaleX) { return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX); }
- float getScaleX() const {
- return mPrimitiveFields.mScaleX;
- }
+ float getScaleX() const { return mPrimitiveFields.mScaleX; }
- bool setScaleY(float scaleY) {
- return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
- }
+ bool setScaleY(float scaleY) { return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY); }
- float getScaleY() const {
- return mPrimitiveFields.mScaleY;
- }
+ float getScaleY() const { return mPrimitiveFields.mScaleY; }
bool setPivotX(float pivotX) {
- if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
- || !mPrimitiveFields.mPivotExplicitlySet) {
+ if (RP_SET(mPrimitiveFields.mPivotX, pivotX) || !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixOrPivotDirty = true;
mPrimitiveFields.mPivotExplicitlySet = true;
return true;
@@ -373,13 +313,10 @@ public:
* so the value returned may be stale if the RenderProperties has been
* modified since the last call to updateMatrix()
*/
- float getPivotX() const {
- return mPrimitiveFields.mPivotX;
- }
+ float getPivotX() const { return mPrimitiveFields.mPivotX; }
bool setPivotY(float pivotY) {
- if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
- || !mPrimitiveFields.mPivotExplicitlySet) {
+ if (RP_SET(mPrimitiveFields.mPivotY, pivotY) || !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixOrPivotDirty = true;
mPrimitiveFields.mPivotExplicitlySet = true;
return true;
@@ -387,12 +324,12 @@ public:
return false;
}
- float getPivotY() const {
- return mPrimitiveFields.mPivotY;
- }
+ float getPivotY() const { return mPrimitiveFields.mPivotY; }
- bool isPivotExplicitlySet() const {
- return mPrimitiveFields.mPivotExplicitlySet;
+ bool isPivotExplicitlySet() const { return mPrimitiveFields.mPivotExplicitlySet; }
+
+ bool resetPivot() {
+ return RP_SET_AND_DIRTY(mPrimitiveFields.mPivotExplicitlySet, false);
}
bool setCameraDistance(float distance) {
@@ -420,9 +357,7 @@ public:
return false;
}
- int getLeft() const {
- return mPrimitiveFields.mLeft;
- }
+ int getLeft() const { return mPrimitiveFields.mLeft; }
bool setTop(int top) {
if (RP_SET(mPrimitiveFields.mTop, top)) {
@@ -435,9 +370,7 @@ public:
return false;
}
- int getTop() const {
- return mPrimitiveFields.mTop;
- }
+ int getTop() const { return mPrimitiveFields.mTop; }
bool setRight(int right) {
if (RP_SET(mPrimitiveFields.mRight, right)) {
@@ -450,9 +383,7 @@ public:
return false;
}
- int getRight() const {
- return mPrimitiveFields.mRight;
- }
+ int getRight() const { return mPrimitiveFields.mRight; }
bool setBottom(int bottom) {
if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
@@ -465,9 +396,7 @@ public:
return false;
}
- int getBottom() const {
- return mPrimitiveFields.mBottom;
- }
+ int getBottom() const { return mPrimitiveFields.mBottom; }
bool setLeftTop(int left, int top) {
bool leftResult = setLeft(left);
@@ -476,8 +405,8 @@ public:
}
bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
- if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
- || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
+ if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop ||
+ right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
mPrimitiveFields.mLeft = left;
mPrimitiveFields.mTop = top;
mPrimitiveFields.mRight = right;
@@ -510,17 +439,11 @@ public:
return false;
}
- int getWidth() const {
- return mPrimitiveFields.mWidth;
- }
+ int getWidth() const { return mPrimitiveFields.mWidth; }
- int getHeight() const {
- return mPrimitiveFields.mHeight;
- }
+ int getHeight() const { return mPrimitiveFields.mHeight; }
- const SkMatrix* getAnimationMatrix() const {
- return mAnimationMatrix;
- }
+ const SkMatrix* getAnimationMatrix() const { return mAnimationMatrix; }
bool hasTransformMatrix() const {
return getTransformMatrix() && !getTransformMatrix()->isIdentity();
@@ -536,17 +459,11 @@ public:
return mComputedFields.mTransformMatrix;
}
- int getClippingFlags() const {
- return mPrimitiveFields.mClippingFlags;
- }
+ int getClippingFlags() const { return mPrimitiveFields.mClippingFlags; }
- bool getClipToBounds() const {
- return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
- }
+ bool getClipToBounds() const { return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS; }
- const Rect& getClipBounds() const {
- return mPrimitiveFields.mClipBounds;
- }
+ const Rect& getClipBounds() const { return mPrimitiveFields.mClipBounds; }
void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
if (flags & CLIP_TO_BOUNDS) {
@@ -559,41 +476,25 @@ public:
}
}
- bool getHasOverlappingRendering() const {
- return mPrimitiveFields.mHasOverlappingRendering;
- }
+ bool getHasOverlappingRendering() const { return mPrimitiveFields.mHasOverlappingRendering; }
- const Outline& getOutline() const {
- return mPrimitiveFields.mOutline;
- }
+ const Outline& getOutline() const { return mPrimitiveFields.mOutline; }
- const RevealClip& getRevealClip() const {
- return mPrimitiveFields.mRevealClip;
- }
+ const RevealClip& getRevealClip() const { return mPrimitiveFields.mRevealClip; }
- bool getProjectBackwards() const {
- return mPrimitiveFields.mProjectBackwards;
- }
+ bool getProjectBackwards() const { return mPrimitiveFields.mProjectBackwards; }
void debugOutputProperties(std::ostream& output, const int level) const;
void updateMatrix();
- Outline& mutableOutline() {
- return mPrimitiveFields.mOutline;
- }
+ Outline& mutableOutline() { return mPrimitiveFields.mOutline; }
- RevealClip& mutableRevealClip() {
- return mPrimitiveFields.mRevealClip;
- }
+ RevealClip& mutableRevealClip() { return mPrimitiveFields.mRevealClip; }
- const LayerProperties& layerProperties() const {
- return mLayerProperties;
- }
+ const LayerProperties& layerProperties() const { return mLayerProperties; }
- LayerProperties& mutateLayerProperties() {
- return mLayerProperties;
- }
+ LayerProperties& mutateLayerProperties() { return mLayerProperties; }
// Returns true if damage calculations should be clipped to bounds
// TODO: Figure out something better for getZ(), as children should still be
@@ -605,24 +506,37 @@ public:
}
bool hasShadow() const {
- return getZ() > 0.0f
- && getOutline().getPath() != nullptr
- && getOutline().getAlpha() != 0.0f;
+ return getZ() > 0.0f && getOutline().getPath() != nullptr &&
+ getOutline().getAlpha() != 0.0f;
+ }
+
+ SkColor getSpotShadowColor() const {
+ return mPrimitiveFields.mSpotShadowColor;
+ }
+
+ bool setSpotShadowColor(SkColor shadowColor) {
+ return RP_SET(mPrimitiveFields.mSpotShadowColor, shadowColor);
+ }
+
+ SkColor getAmbientShadowColor() const {
+ return mPrimitiveFields.mAmbientShadowColor;
+ }
+
+ bool setAmbientShadowColor(SkColor shadowColor) {
+ return RP_SET(mPrimitiveFields.mAmbientShadowColor, shadowColor);
}
bool fitsOnLayer() const {
const DeviceInfo* deviceInfo = DeviceInfo::get();
- return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
- && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
+ return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize() &&
+ mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
}
bool promotedToLayer() const {
- return mLayerProperties.mType == LayerType::None
- && fitsOnLayer()
- && (mComputedFields.mNeedLayerForFunctors
- || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
- && mPrimitiveFields.mAlpha < 1
- && mPrimitiveFields.mHasOverlappingRendering));
+ return mLayerProperties.mType == LayerType::None && fitsOnLayer() &&
+ (mComputedFields.mNeedLayerForFunctors ||
+ (!MathUtils::isZero(mPrimitiveFields.mAlpha) && mPrimitiveFields.mAlpha < 1 &&
+ mPrimitiveFields.mHasOverlappingRendering));
}
LayerType effectiveLayerType() const {
@@ -635,6 +549,8 @@ private:
int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
int mWidth = 0, mHeight = 0;
int mClippingFlags = CLIP_TO_BOUNDS;
+ SkColor mSpotShadowColor = SK_ColorBLACK;
+ SkColor mAmbientShadowColor = SK_ColorBLACK;
float mAlpha = 1;
float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
float mElevation = 0;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index b26e433cfa4c..d60b99469368 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -32,10 +32,10 @@ void ResourceCache::logCache() {
ALOGD("ResourceCache: cacheReport:");
for (size_t i = 0; i < mCache->size(); ++i) {
ResourceReference* ref = mCache->valueAt(i);
- ALOGD(" ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p",
- i, mCache->keyAt(i), mCache->valueAt(i));
- ALOGD(" ResourceCache: mCache(%zu): refCount, destroyed, type = %d, %d, %d",
- i, ref->refCount, ref->destroyed, ref->resourceType);
+ ALOGD(" ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p", i, mCache->keyAt(i),
+ mCache->valueAt(i));
+ ALOGD(" ResourceCache: mCache(%zu): refCount, destroyed, type = %d, %d, %d", i,
+ ref->refCount, ref->destroyed, ref->resourceType);
}
}
@@ -63,7 +63,7 @@ void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType)
}
void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
- incrementRefcount((void*) patchResource, kNinePatch);
+ incrementRefcount((void*)patchResource, kNinePatch);
}
void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
@@ -82,7 +82,7 @@ void ResourceCache::decrementRefcount(void* resource) {
}
void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
- decrementRefcount((void*) patchResource);
+ decrementRefcount((void*)patchResource);
}
void ResourceCache::decrementRefcountLocked(void* resource) {
@@ -99,7 +99,7 @@ void ResourceCache::decrementRefcountLocked(void* resource) {
}
void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
- decrementRefcountLocked((void*) patchResource);
+ decrementRefcountLocked((void*)patchResource);
}
void ResourceCache::destructor(Res_png_9patch* resource) {
@@ -117,7 +117,7 @@ void ResourceCache::destructorLocked(Res_png_9patch* resource) {
} else {
// A Res_png_9patch is actually an array of byte that's larger
// than sizeof(Res_png_9patch). It must be freed as an array.
- delete[] (int8_t*) resource;
+ delete[](int8_t*) resource;
}
return;
}
@@ -136,20 +136,19 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource
switch (ref->resourceType) {
case kNinePatch: {
if (Caches::hasInstance()) {
- Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
+ Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*)resource);
} else {
// A Res_png_9patch is actually an array of byte that's larger
// than sizeof(Res_png_9patch). It must be freed as an array.
- int8_t* patch = (int8_t*) resource;
+ int8_t* patch = (int8_t*)resource;
delete[] patch;
}
- }
- break;
+ } break;
}
}
mCache->removeItem(resource);
delete ref;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 3ac78642c7ee..fd3f9fd05d58 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -41,9 +41,10 @@ enum ResourceType {
class ResourceReference {
public:
-
explicit ResourceReference(ResourceType type) {
- refCount = 0; destroyed = false; resourceType = type;
+ refCount = 0;
+ destroyed = false;
+ resourceType = type;
}
int refCount;
@@ -51,14 +52,13 @@ public:
ResourceType resourceType;
};
-class ANDROID_API ResourceCache: public Singleton<ResourceCache> {
+class ANDROID_API ResourceCache : public Singleton<ResourceCache> {
ResourceCache();
~ResourceCache();
friend class Singleton<ResourceCache>;
public:
-
/**
* When using these two methods, make sure to only invoke the *Locked()
* variants of increment/decrementRefcount(), recyle() and destructor()
@@ -97,7 +97,7 @@ private:
KeyedVector<const void*, ResourceReference*>* mCache;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_RESOURCE_CACHE_H
+#endif // ANDROID_HWUI_RESOURCE_CACHE_H
diff --git a/libs/hwui/RevealClip.h b/libs/hwui/RevealClip.h
index 63821dddd369..a5678d48482a 100644
--- a/libs/hwui/RevealClip.h
+++ b/libs/hwui/RevealClip.h
@@ -25,11 +25,7 @@ namespace uirenderer {
class RevealClip {
public:
- RevealClip()
- : mShouldClip(false)
- , mX(0)
- , mY(0)
- , mRadius(0) {}
+ RevealClip() : mShouldClip(false), mX(0), mY(0), mRadius(0) {}
void set(bool shouldClip, float x, float y, float radius) {
mShouldClip = shouldClip;
@@ -43,13 +39,10 @@ public:
}
}
- bool willClip() const {
- return mShouldClip;
- }
+ bool willClip() const { return mShouldClip; }
void getBounds(Rect* outBounds) const {
- outBounds->set(mX - mRadius, mY - mRadius,
- mX + mRadius, mY + mRadius);
+ outBounds->set(mX - mRadius, mY - mRadius, mX + mRadius, mY + mRadius);
}
float getRadius() const { return mRadius; }
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index e94a70a9f80d..d0155ee473f7 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -16,8 +16,8 @@
#include <math.h>
#include <utils/Log.h>
-#include <utils/Trace.h>
#include <utils/MathUtils.h>
+#include <utils/Trace.h>
#include "AmbientShadow.h"
#include "Properties.h"
@@ -28,10 +28,10 @@
namespace android {
namespace uirenderer {
-void ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque,
- const Vector3* casterPolygon, int casterVertexCount,
- const Vector3& centroid3d, const Rect& casterBounds,
- const Rect& localClip, float maxZ, VertexBuffer& shadowVertexBuffer) {
+void ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque, const Vector3* casterPolygon,
+ int casterVertexCount, const Vector3& centroid3d,
+ const Rect& casterBounds, const Rect& localClip,
+ float maxZ, VertexBuffer& shadowVertexBuffer) {
ATRACE_CALL();
// A bunch of parameters to tweak the shadow.
@@ -53,32 +53,32 @@ void ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque,
return;
}
- AmbientShadow::createAmbientShadow(isCasterOpaque, casterPolygon,
- casterVertexCount, centroid3d, heightFactor, geomFactor,
- shadowVertexBuffer);
+ AmbientShadow::createAmbientShadow(isCasterOpaque, casterPolygon, casterVertexCount, centroid3d,
+ heightFactor, geomFactor, shadowVertexBuffer);
}
-void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
- const Vector3* casterPolygon, int casterVertexCount, const Vector3& casterCentroid,
- const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius,
- const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer) {
+void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque, const Vector3* casterPolygon,
+ int casterVertexCount, const Vector3& casterCentroid,
+ const mat4& receiverTransform,
+ const Vector3& lightCenter, int lightRadius,
+ const Rect& casterBounds, const Rect& localClip,
+ VertexBuffer& shadowVertexBuffer) {
ATRACE_CALL();
Vector3 adjustedLightCenter(lightCenter);
if (CC_UNLIKELY(Properties::overrideLightPosY > 0)) {
- adjustedLightCenter.y = - Properties::overrideLightPosY; // negated since this shifts up
+ adjustedLightCenter.y = -Properties::overrideLightPosY; // negated since this shifts up
}
if (CC_UNLIKELY(Properties::overrideLightPosZ > 0)) {
adjustedLightCenter.z = Properties::overrideLightPosZ;
}
#if DEBUG_SHADOW
- ALOGD("light center %f %f %f %d",
- adjustedLightCenter.x, adjustedLightCenter.y, adjustedLightCenter.z, lightRadius);
+ ALOGD("light center %f %f %f %d", adjustedLightCenter.x, adjustedLightCenter.y,
+ adjustedLightCenter.z, lightRadius);
#endif
- if (isnan(adjustedLightCenter.x)
- || isnan(adjustedLightCenter.y)
- || isnan(adjustedLightCenter.z)) {
+ if (isnan(adjustedLightCenter.x) || isnan(adjustedLightCenter.y) ||
+ isnan(adjustedLightCenter.z)) {
return;
}
@@ -95,7 +95,7 @@ void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
// Now light and caster are both in local space, we will check whether
// the shadow is within the clip area.
Rect lightRect = Rect(adjustedLightCenter.x - lightRadius, adjustedLightCenter.y - lightRadius,
- adjustedLightCenter.x + lightRadius, adjustedLightCenter.y + lightRadius);
+ adjustedLightCenter.x + lightRadius, adjustedLightCenter.y + lightRadius);
lightRect.unionWith(localClip);
if (!lightRect.intersects(casterBounds)) {
#if DEBUG_SHADOW
@@ -104,13 +104,13 @@ void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
return;
}
- SpotShadow::createSpotShadow(isCasterOpaque, adjustedLightCenter, lightRadius,
- casterPolygon, casterVertexCount, casterCentroid, shadowVertexBuffer);
+ SpotShadow::createSpotShadow(isCasterOpaque, adjustedLightCenter, lightRadius, casterPolygon,
+ casterVertexCount, casterCentroid, shadowVertexBuffer);
#if DEBUG_SHADOW
- if(shadowVertexBuffer.getVertexCount() <= 0) {
+ if (shadowVertexBuffer.getVertexCount() <= 0) {
ALOGD("Spot shadow generation failed %d", shadowVertexBuffer.getVertexCount());
- }
+ }
#endif
}
@@ -141,7 +141,7 @@ Vector2 ShadowTessellator::centroid2d(const Vector2* poly, int polyLength) {
Vector2 centroid = poly[0];
if (area != 0) {
centroid = (Vector2){static_cast<float>(sumx / (3 * area)),
- static_cast<float>(sumy / (3 * area))};
+ static_cast<float>(sumy / (3 * area))};
} else {
ALOGW("Area is 0 while computing centroid!");
}
@@ -161,8 +161,8 @@ Vector2 ShadowTessellator::calculateNormal(const Vector2& p1, const Vector2& p2)
return result;
}
-int ShadowTessellator::getExtraVertexNumber(const Vector2& vector1,
- const Vector2& vector2, float divisor) {
+int ShadowTessellator::getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2,
+ float divisor) {
// When there is no distance difference, there is no need for extra vertices.
if (vector1.lengthSquared() == 0 || vector2.lengthSquared() == 0) {
return 0;
@@ -179,13 +179,13 @@ int ShadowTessellator::getExtraVertexNumber(const Vector2& vector1,
// TODO: Use look up table for the dotProduct to extraVerticesNumber
// computation, if needed.
float angle = acosf(dotProduct);
- return (int) floor(angle / divisor);
+ return (int)floor(angle / divisor);
}
void ShadowTessellator::checkOverflow(int used, int total, const char* bufferName) {
- LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d",
- bufferName, used, total);
+ LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d", bufferName, used,
+ total);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index 2eaf187a1af1..79f46f9e9a06 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -68,27 +68,27 @@ class VertexBuffer;
class ShadowTessellator {
public:
- static void tessellateAmbientShadow(bool isCasterOpaque,
- const Vector3* casterPolygon, int casterVertexCount,
- const Vector3& centroid3d, const Rect& casterBounds,
- const Rect& localClip, float maxZ, VertexBuffer& shadowVertexBuffer);
+ static void tessellateAmbientShadow(bool isCasterOpaque, const Vector3* casterPolygon,
+ int casterVertexCount, const Vector3& centroid3d,
+ const Rect& casterBounds, const Rect& localClip, float maxZ,
+ VertexBuffer& shadowVertexBuffer);
- static void tessellateSpotShadow(bool isCasterOpaque,
- const Vector3* casterPolygon, int casterVertexCount, const Vector3& casterCentroid,
- const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius,
- const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer);
+ static void tessellateSpotShadow(bool isCasterOpaque, const Vector3* casterPolygon,
+ int casterVertexCount, const Vector3& casterCentroid,
+ const mat4& receiverTransform, const Vector3& lightCenter,
+ int lightRadius, const Rect& casterBounds,
+ const Rect& localClip, VertexBuffer& shadowVertexBuffer);
static Vector2 centroid2d(const Vector2* poly, int polyLength);
static Vector2 calculateNormal(const Vector2& p1, const Vector2& p2);
- static int getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2,
- float divisor);
+ static int getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2, float divisor);
static void checkOverflow(int used, int total, const char* bufferName);
-}; // ShadowTessellator
+}; // ShadowTessellator
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_SHADOW_TESSELLATOR_H
+#endif // ANDROID_HWUI_SHADOW_TESSELLATOR_H
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 0a642b60d4c7..40b811d813fd 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -23,14 +23,17 @@
#include "hwui/MinikinUtils.h"
#include "pipeline/skia/AnimatedDrawables.h"
+#include <SkAnimatedImage.h>
#include <SkCanvasStateUtils.h>
+#include <SkColorFilter.h>
#include <SkColorSpaceXformCanvas.h>
-#include <SkDrawable.h>
#include <SkDeque.h>
#include <SkDrawFilter.h>
+#include <SkDrawable.h>
#include <SkGraphics.h>
#include <SkImage.h>
#include <SkImagePriv.h>
+#include <SkPicture.h>
#include <SkRSXform.h>
#include <SkShader.h>
#include <SkTemplates.h>
@@ -46,25 +49,34 @@ Canvas* Canvas::create_canvas(const SkBitmap& bitmap) {
return new SkiaCanvas(bitmap);
}
-Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas, XformToSRGB xformToSRGB) {
- return new SkiaCanvas(skiaCanvas, xformToSRGB);
+Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
+ return new SkiaCanvas(skiaCanvas);
}
SkiaCanvas::SkiaCanvas() {}
-SkiaCanvas::SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB)
- : mCanvas(canvas)
-{
- LOG_ALWAYS_FATAL_IF(XformToSRGB::kImmediate == xformToSRGB);
-}
+SkiaCanvas::SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {}
SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
mCanvasOwned =
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(),
- cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
- mCanvas = mCanvasWrapper.get();
+ if (cs.get() == nullptr || cs->isSRGB()) {
+ if (!uirenderer::Properties::isSkiaEnabled()) {
+ mCanvasWrapper =
+ SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), SkColorSpace::MakeSRGB());
+ mCanvas = mCanvasWrapper.get();
+ } else {
+ mCanvas = mCanvasOwned.get();
+ }
+ } else {
+ /** The wrapper is needed if we are drawing into a non-sRGB destination, since
+ * we need to transform all colors (not just bitmaps via filters) into the
+ * destination's colorspace.
+ */
+ mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), std::move(cs));
+ mCanvas = mCanvasWrapper.get();
+ }
}
SkiaCanvas::~SkiaCanvas() {}
@@ -73,9 +85,9 @@ void SkiaCanvas::reset(SkCanvas* skiaCanvas) {
if (mCanvas != skiaCanvas) {
mCanvas = skiaCanvas;
mCanvasOwned.reset();
+ mCanvasWrapper.reset();
}
mSaveStack.reset(nullptr);
- mHighContrastText = false;
}
// ----------------------------------------------------------------------------
@@ -86,13 +98,17 @@ void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
std::unique_ptr<SkCanvas> newCanvas =
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- std::unique_ptr<SkCanvas> newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(),
- cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
+ std::unique_ptr<SkCanvas> newCanvasWrapper;
+ if (cs.get() != nullptr && !cs->isSRGB()) {
+ newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), std::move(cs));
+ } else if (!uirenderer::Properties::isSkiaEnabled()) {
+ newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), SkColorSpace::MakeSRGB());
+ }
// deletes the previously owned canvas (if any)
mCanvasOwned = std::move(newCanvas);
mCanvasWrapper = std::move(newCanvasWrapper);
- mCanvas = mCanvasWrapper.get();
+ mCanvas = mCanvasWrapper ? mCanvasWrapper.get() : mCanvasOwned.get();
// clean up the old save stack
mSaveStack.reset(nullptr);
@@ -141,7 +157,7 @@ void SkiaCanvas::restore() {
}
bool preserveMatrix = !(rec->saveFlags & SaveFlags::Matrix);
- bool preserveClip = !(rec->saveFlags & SaveFlags::Clip);
+ bool preserveClip = !(rec->saveFlags & SaveFlags::Clip);
SkMatrix savedMatrix;
if (preserveMatrix) {
@@ -171,11 +187,6 @@ void SkiaCanvas::restoreToCount(int restoreCount) {
static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) {
SkCanvas::SaveLayerFlags layerFlags = 0;
- // We intentionally ignore the SaveFlags::HasAlphaLayer and
- // SkCanvas::kIsOpaque_SaveLayerFlag flags because HWUI ignores it
- // and our Android client may use it incorrectly.
- // In Skia, this flag is purely for performance optimization.
-
if (!(flags & SaveFlags::ClipToLayer)) {
layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag;
}
@@ -183,16 +194,16 @@ static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) {
return layerFlags;
}
-int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SaveFlags::Flags flags) {
+int SkiaCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+ SaveFlags::Flags flags) {
const SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags));
return mCanvas->saveLayer(rec);
}
-int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SaveFlags::Flags flags) {
+int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
+ SaveFlags::Flags flags) {
if (static_cast<unsigned>(alpha) < 0xFF) {
SkPaint alphaPaint;
alphaPaint.setAlpha(alpha);
@@ -204,24 +215,24 @@ int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
class SkiaCanvas::Clip {
public:
Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
- : mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
+ : mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
- : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
+ : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
- : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
+ : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
void apply(SkCanvas* canvas) const {
canvas->setMatrix(mMatrix);
switch (mType) {
- case Type::Rect:
- canvas->clipRect(mRRect.rect(), mOp);
- break;
- case Type::RRect:
- canvas->clipRRect(mRRect, mOp);
- break;
- case Type::Path:
- canvas->clipPath(*mPath.get(), mOp);
- break;
+ case Type::Rect:
+ canvas->clipRect(mRRect.rect(), mOp);
+ break;
+ case Type::RRect:
+ canvas->clipRRect(mRRect, mOp);
+ break;
+ case Type::Path:
+ canvas->clipPath(*mPath.get(), mOp);
+ break;
}
}
@@ -232,19 +243,17 @@ private:
Path,
};
- Type mType;
- SkClipOp mOp;
- SkMatrix mMatrix;
+ Type mType;
+ SkClipOp mOp;
+ SkMatrix mMatrix;
// These are logically a union (tracked separately due to non-POD path).
SkTLazy<SkPath> mPath;
- SkRRect mRRect;
+ SkRRect mRRect;
};
const SkiaCanvas::SaveRec* SkiaCanvas::currentSaveRec() const {
- const SaveRec* rec = mSaveStack
- ? static_cast<const SaveRec*>(mSaveStack->back())
- : nullptr;
+ const SaveRec* rec = mSaveStack ? static_cast<const SaveRec*>(mSaveStack->back()) : nullptr;
int currentSaveCount = mCanvas->getSaveCount();
SkASSERT(!rec || currentSaveCount >= rec->saveCount);
@@ -422,10 +431,9 @@ SkCanvasState* SkiaCanvas::captureCanvasState() const {
// translate & scale transforms, and a simple rectangular clip.
// (This also avoids significant wasted time in calling
// SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
- if (!canvas->isClipRect() ||
- (canvas->getTotalMatrix().getType() &
- ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
- return nullptr;
+ if (!canvas->isClipRect() || (canvas->getTotalMatrix().getType() &
+ ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
+ return nullptr;
}
return SkCanvasStateUtils::CaptureCanvasState(canvas);
@@ -451,7 +459,7 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint
SkCanvas::PointMode mode) {
if (CC_UNLIKELY(count < 2 || paint.nothingToDraw())) return;
// convert the floats into SkPoints
- count >>= 1; // now it is the number of points
+ count >>= 1; // now it is the number of points
std::unique_ptr<SkPoint[]> pts(new SkPoint[count]);
for (int i = 0; i < count; i++) {
pts[i].set(points[0], points[1]);
@@ -460,7 +468,6 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint
mCanvas->drawPoints(mode, count, pts.get(), paint);
}
-
void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
mCanvas->drawPoint(x, y, paint);
}
@@ -479,11 +486,9 @@ void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint)
this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
}
-void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) {
+void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
mCanvas->drawRect({left, top, right, bottom}, paint);
-
}
void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
@@ -491,8 +496,8 @@ void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
mCanvas->drawRegion(region, paint);
}
-void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) {
+void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+ const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
mCanvas->drawRoundRect(rect, rx, ry, paint);
@@ -509,15 +514,22 @@ void SkiaCanvas::drawOval(float left, float top, float right, float bottom, cons
mCanvas->drawOval(oval, paint);
}
-void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
+void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, bool useCenter, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
- mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
+ if (fabs(sweepAngle) >= 360.0f) {
+ mCanvas->drawOval(arc, paint);
+ } else {
+ mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
+ }
}
void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
+ if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) {
+ return;
+ }
mCanvas->drawPath(path, paint);
}
@@ -529,26 +541,65 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons
// Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
+const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
+ sk_sp<SkColorFilter> colorSpaceFilter) {
+ /* We don't apply the colorSpace filter if this canvas is already wrapped with
+ * a SkColorSpaceXformCanvas since it already takes care of converting the
+ * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper
+ * should only be used if this canvas is backed by a surface/bitmap that is known
+ * to have a non-sRGB colorspace.
+ */
+ if (!mCanvasWrapper && colorSpaceFilter) {
+ if (origPaint) {
+ *tmpPaint = *origPaint;
+ }
+
+ if (tmpPaint->getColorFilter()) {
+ tmpPaint->setColorFilter(
+ SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter));
+ LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
+ } else {
+ tmpPaint->setColorFilter(colorSpaceFilter);
+ }
+
+ return tmpPaint;
+ } else {
+ return origPaint;
+ }
+}
+
void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
- mCanvas->drawImage(bitmap.makeImage(), left, top, paint);
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImage(image, left, top, addFilter(paint, &tmpPaint, colorFilter));
}
-void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, const SkPaint* paint) {
+void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
SkAutoCanvasRestore acr(mCanvas, true);
mCanvas->concat(matrix);
- mCanvas->drawImage(hwuiBitmap.makeImage(), 0, 0, paint);
+
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImage(image, 0, 0, addFilter(paint, &tmpPaint, colorFilter));
}
-void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) {
+void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) {
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- mCanvas->drawImageRect(hwuiBitmap.makeImage(), srcRect, dstRect, paint);
+
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter),
+ SkCanvas::kFast_SrcRectConstraint);
}
-void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) {
+void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
+ const float* vertices, const int* colors, const SkPaint* paint) {
const int ptCount = (meshWidth + 1) * (meshHeight + 1);
const int indexCount = meshWidth * meshHeight * 6;
uint32_t flags = SkVertices::kHasTexCoords_BuilderFlag;
@@ -565,8 +616,8 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
// cons up texture coordinates and indices
{
- const SkScalar w = SkIntToScalar(hwuiBitmap.width());
- const SkScalar h = SkIntToScalar(hwuiBitmap.height());
+ const SkScalar w = SkIntToScalar(bitmap.width());
+ const SkScalar h = SkIntToScalar(bitmap.height());
const SkScalar dx = w / meshWidth;
const SkScalar dy = h / meshHeight;
@@ -612,7 +663,7 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
SkASSERT(indexPtr - indices == indexCount);
}
- // double-check that we have legal indices
+// double-check that we have legal indices
#ifdef SK_DEBUG
{
for (int i = 0; i < indexCount; i++) {
@@ -627,19 +678,26 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
tmpPaint = *paint;
}
- sk_sp<SkImage> image = hwuiBitmap.makeImage();
- tmpPaint.setShader(image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ sk_sp<SkShader> shader =
+ image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+ if (colorFilter) {
+ shader = shader->makeWithColorFilter(colorFilter);
+ }
+ tmpPaint.setShader(shader);
mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint);
}
-void SkiaCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
-
+void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft,
+ float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) {
SkCanvas::Lattice lattice;
- NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
+ NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
- lattice.fFlags = nullptr;
+ lattice.fRectTypes = nullptr;
+ lattice.fColors = nullptr;
int numFlags = 0;
if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) {
// We can expect the framework to give us a color for every distinct rect.
@@ -647,14 +705,23 @@ void SkiaCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
}
- SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags);
+ SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags);
+ SkAutoSTMalloc<25, SkColor> colors(numFlags);
if (numFlags > 0) {
- NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk);
+ NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
}
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- mCanvas->drawImageLattice(hwuiBitmap.makeImage().get(), lattice, dst, paint);
+
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter));
+}
+
+double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) {
+ return imgDrawable->drawStaging(mCanvas);
}
void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
@@ -666,17 +733,24 @@ void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
// ----------------------------------------------------------------------------
void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& paint, float x,
- float y, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
- float totalAdvance) {
+ float y, float boundsLeft, float boundsTop, float boundsRight,
+ float boundsBottom, float totalAdvance) {
if (count <= 0 || paint.nothingToDraw()) return;
// Set align to left for drawing, as we don't want individual
// glyphs centered or right-aligned; the offset above takes
// care of all alignment.
SkPaint paintCopy(paint);
paintCopy.setTextAlign(SkPaint::kLeft_Align);
+ SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
+ // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and
+ // older.
+ if (!mCanvasOwned && sApiLevel <= 27 && paintCopy.getStrokeWidth() <= 0
+ && paintCopy.getStyle() == SkPaint::kStroke_Style) {
+ paintCopy.setStyle(SkPaint::kFill_Style);
+ }
- SkRect bounds = SkRect::MakeLTRB(boundsLeft + x, boundsTop + y,
- boundsRight + x, boundsBottom + y);
+ SkRect bounds =
+ SkRect::MakeLTRB(boundsLeft + x, boundsTop + y, boundsRight + x, boundsBottom + y);
SkTextBlobBuilder builder;
const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(paintCopy, count, &bounds);
@@ -688,7 +762,15 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p
}
void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
- const SkPaint& paint, const SkPath& path, size_t start, size_t end) {
+ const SkPaint& paint, const SkPath& path, size_t start,
+ size_t end) {
+ // Set align to left for drawing, as we don't want individual
+ // glyphs centered or right-aligned; the offsets take care of
+ // that portion of the alignment.
+ SkPaint paintCopy(paint);
+ paintCopy.setTextAlign(SkPaint::kLeft_Align);
+ SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
+
const int N = end - start;
SkAutoSTMalloc<1024, uint8_t> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform)));
SkRSXform* xform = (SkRSXform*)storage.get();
@@ -697,7 +779,8 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
for (size_t i = start; i < end; i++) {
glyphs[i - start] = layout.getGlyphId(i);
- float x = hOffset + layout.getX(i);
+ float halfWidth = layout.getCharAdvance(i) * 0.5f;
+ float x = hOffset + layout.getX(i) + halfWidth;
float y = vOffset + layout.getY(i);
SkPoint pos;
@@ -708,11 +791,11 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
}
xform[i - start].fSCos = tan.x();
xform[i - start].fSSin = tan.y();
- xform[i - start].fTx = pos.x() - tan.y() * y;
- xform[i - start].fTy = pos.y() + tan.x() * y;
+ xform[i - start].fTx = pos.x() - tan.y() * y - halfWidth * tan.x();
+ xform[i - start].fTy = pos.y() + tan.x() * y - halfWidth * tan.y();
}
- this->asSkCanvas()->drawTextRSXform(glyphs, sizeof(uint16_t) * N, xform, nullptr, paint);
+ this->asSkCanvas()->drawTextRSXform(glyphs, sizeof(uint16_t) * N, xform, nullptr, paintCopy);
}
// ----------------------------------------------------------------------------
@@ -720,17 +803,24 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
// ----------------------------------------------------------------------------
void SkiaCanvas::drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
- uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
- uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
- uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) {
+ uirenderer::CanvasPropertyPrimitive* top,
+ uirenderer::CanvasPropertyPrimitive* right,
+ uirenderer::CanvasPropertyPrimitive* bottom,
+ uirenderer::CanvasPropertyPrimitive* rx,
+ uirenderer::CanvasPropertyPrimitive* ry,
+ uirenderer::CanvasPropertyPaint* paint) {
sk_sp<uirenderer::skiapipeline::AnimatedRoundRect> drawable(
- new uirenderer::skiapipeline::AnimatedRoundRect(left, top, right, bottom, rx, ry, paint));
+ new uirenderer::skiapipeline::AnimatedRoundRect(left, top, right, bottom, rx, ry,
+ paint));
mCanvas->drawDrawable(drawable.get());
}
-void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y,
- uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) {
- sk_sp<uirenderer::skiapipeline::AnimatedCircle> drawable(new uirenderer::skiapipeline::AnimatedCircle(x, y, radius, paint));
+void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x,
+ uirenderer::CanvasPropertyPrimitive* y,
+ uirenderer::CanvasPropertyPrimitive* radius,
+ uirenderer::CanvasPropertyPaint* paint) {
+ sk_sp<uirenderer::skiapipeline::AnimatedCircle> drawable(
+ new uirenderer::skiapipeline::AnimatedCircle(x, y, radius, paint));
mCanvas->drawDrawable(drawable.get());
}
@@ -747,8 +837,8 @@ void SkiaCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) {
}
void SkiaCanvas::callDrawGLFunction(Functor* functor,
- uirenderer::GlFunctorLifecycleListener* listener) {
+ uirenderer::GlFunctorLifecycleListener* listener) {
LOG_ALWAYS_FATAL("SkiaCanvas can't directly draw GL Content");
}
-} // namespace android
+} // namespace android
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index af2c23e4a2b7..3efc22a03cdf 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -15,11 +15,11 @@
*/
#pragma once
-#include "hwui/Canvas.h"
#include "CanvasProperty.h"
#include "DeferredLayerUpdater.h"
#include "RenderNode.h"
#include "VectorDrawable.h"
+#include "hwui/Canvas.h"
#include <SkCanvas.h>
#include <SkTLazy.h>
@@ -37,21 +37,15 @@ public:
* @param canvas SkCanvas to handle calls made to this SkiaCanvas. Must
* not be NULL. This constructor does not take ownership, so the caller
* must guarantee that it remains valid while the SkiaCanvas is valid.
- * @param xformToSRGB Indicates if bitmaps should be xformed to the sRGB
- * color space before drawing. This makes sense for software rendering.
- * For the picture case, it may make more sense to leave bitmaps as is,
- * and handle the xform when replaying the picture.
*/
- explicit SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB);
+ explicit SkiaCanvas(SkCanvas* canvas);
virtual ~SkiaCanvas();
- virtual SkCanvas* asSkCanvas() override {
- return mCanvas;
- }
+ virtual SkCanvas* asSkCanvas() override { return mCanvas; }
virtual void resetRecording(int width, int height,
- uirenderer::RenderNode* renderNode) override {
+ uirenderer::RenderNode* renderNode) override {
LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas");
}
@@ -69,20 +63,15 @@ public:
virtual int width() override;
virtual int height() override;
- virtual void setHighContrastText(bool highContrastText) override {
- mHighContrastText = highContrastText;
- }
- virtual bool isHighContrastText() override { return mHighContrastText; }
-
virtual int getSaveCount() const override;
virtual int save(SaveFlags::Flags flags) override;
virtual void restore() override;
virtual void restoreToCount(int saveCount) override;
- virtual int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SaveFlags::Flags flags) override;
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SaveFlags::Flags flags) override;
+ virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+ SaveFlags::Flags flags) override;
+ virtual int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
+ SaveFlags::Flags flags) override;
virtual void getMatrix(SkMatrix* outMatrix) const override;
virtual void setMatrix(const SkMatrix& matrix) override;
@@ -95,8 +84,7 @@ public:
virtual bool getClipBounds(SkRect* outRect) const override;
virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
virtual bool quickRejectPath(const SkPath& path) const override;
- virtual bool clipRect(float left, float top, float right, float bottom,
- SkClipOp op) override;
+ virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override;
virtual bool clipPath(const SkPath* path, SkClipOp op) override;
virtual SkDrawFilter* getDrawFilter() override;
@@ -110,47 +98,53 @@ public:
virtual void drawPoint(float x, float y, const SkPaint& paint) override;
virtual void drawPoints(const float* points, int count, const SkPaint& paint) override;
virtual void drawLine(float startX, float startY, float stopX, float stopY,
- const SkPaint& paint) override;
+ const SkPaint& paint) override;
virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
virtual void drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) override;
+ const SkPaint& paint) override;
virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override;
- virtual void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) override;
+ virtual void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+ const SkPaint& paint) override;
virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
virtual void drawOval(float left, float top, float right, float bottom,
- const SkPaint& paint) override;
- virtual void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override;
+ const SkPaint& paint) override;
+ virtual void drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, bool useCenter, const SkPaint& paint) override;
virtual void drawPath(const SkPath& path, const SkPaint& paint) override;
virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint& paint) override;
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override;
- virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) override;
+ virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) override;
virtual void drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) override;
- virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkPaint* paint) override;
-
- virtual bool drawTextAbsolutePos() const override { return true; }
+ const float* vertices, const int* colors,
+ const SkPaint* paint) override;
+ virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk, float dstLeft,
+ float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) override;
+ virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) override;
+
+ virtual bool drawTextAbsolutePos() const override { return true; }
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
- uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
- uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
- uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) override;
+ uirenderer::CanvasPropertyPrimitive* top,
+ uirenderer::CanvasPropertyPrimitive* right,
+ uirenderer::CanvasPropertyPrimitive* bottom,
+ uirenderer::CanvasPropertyPrimitive* rx,
+ uirenderer::CanvasPropertyPrimitive* ry,
+ uirenderer::CanvasPropertyPaint* paint) override;
virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x,
- uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
- uirenderer::CanvasPropertyPaint* paint) override;
+ uirenderer::CanvasPropertyPrimitive* y,
+ uirenderer::CanvasPropertyPrimitive* radius,
+ uirenderer::CanvasPropertyPaint* paint) override;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
virtual void callDrawGLFunction(Functor* functor,
- uirenderer::GlFunctorLifecycleListener* listener) override;
+ uirenderer::GlFunctorLifecycleListener* listener) override;
protected:
SkiaCanvas();
@@ -158,39 +152,39 @@ protected:
void drawDrawable(SkDrawable* drawable) { mCanvas->drawDrawable(drawable); }
virtual void drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& paint, float x,
- float y, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
- float totalAdvance) override;
+ float y, float boundsLeft, float boundsTop, float boundsRight,
+ float boundsBottom, float totalAdvance) override;
virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
- const SkPaint& paint, const SkPath& path, size_t start, size_t end) override;
+ const SkPaint& paint, const SkPath& path, size_t start,
+ size_t end) override;
private:
struct SaveRec {
- int saveCount;
+ int saveCount;
SaveFlags::Flags saveFlags;
- size_t clipIndex;
+ size_t clipIndex;
};
- bool mHighContrastText = false;
-
const SaveRec* currentSaveRec() const;
void recordPartialSave(SaveFlags::Flags flags);
- template<typename T>
+ template <typename T>
void recordClip(const T&, SkClipOp);
void applyPersistentClips(size_t clipStartIndex);
- void drawPoints(const float* points, int count, const SkPaint& paint,
- SkCanvas::PointMode mode);
+ void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode);
+
+ const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
+ sk_sp<SkColorFilter> colorSpaceFilter);
class Clip;
- std::unique_ptr<SkCanvas> mCanvasWrapper; // might own a wrapper on the canvas
- std::unique_ptr<SkCanvas> mCanvasOwned; // might own a canvas we allocated
- SkCanvas* mCanvas; // we do NOT own this canvas, it must survive us
- // unless it is the same as mCanvasOwned.get()
- std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
- std::vector<Clip> mClipStack; // tracks persistent clips.
+ std::unique_ptr<SkCanvas> mCanvasWrapper; // might own a wrapper on the canvas
+ std::unique_ptr<SkCanvas> mCanvasOwned; // might own a canvas we allocated
+ SkCanvas* mCanvas; // we do NOT own this canvas, it must survive us
+ // unless it is the same as mCanvasOwned.get()
+ std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
+ std::vector<Clip> mClipStack; // tracks persistent clips.
};
-} // namespace android
-
+} // namespace android
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 16a19ca4d36a..fc009d871620 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -20,18 +20,18 @@
#include <log/log.h>
-#include "hwui/Bitmap.h"
#include <SkLatticeIter.h>
-#include <SkPatchUtils.h>
#include <SkPaint.h>
+#include <SkPatchUtils.h>
#include <SkPath.h>
#include <SkPixelRef.h>
-#include <SkRect.h>
#include <SkRRect.h>
#include <SkRSXform.h>
+#include <SkRect.h>
#include <SkSurface.h>
#include <SkTextBlobRunIterator.h>
#include <SkVertices.h>
+#include "hwui/Bitmap.h"
namespace android {
namespace uirenderer {
@@ -46,13 +46,13 @@ void SkiaCanvasProxy::onDrawPaint(const SkPaint& paint) {
}
void SkiaCanvasProxy::onDrawPoints(PointMode pointMode, size_t count, const SkPoint pts[],
- const SkPaint& paint) {
+ const SkPaint& paint) {
if (!pts || count == 0) {
return;
}
// convert the SkPoints into floats
- static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
+ static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
const size_t floatCount = count << 1;
const float* floatArray = &pts[0].fX;
@@ -72,7 +72,7 @@ void SkiaCanvasProxy::onDrawPoints(PointMode pointMode, size_t count, const SkPo
SkPath path;
for (size_t i = 0; i < count - 1; i++) {
path.moveTo(pts[i]);
- path.lineTo(pts[i+1]);
+ path.lineTo(pts[i + 1]);
this->drawPath(path, strokedPaint);
path.rewind();
}
@@ -95,8 +95,8 @@ void SkiaCanvasProxy::onDrawRRect(const SkRRect& roundRect, const SkPaint& paint
if (!roundRect.isComplex()) {
const SkRect& rect = roundRect.rect();
SkVector radii = roundRect.getSimpleRadii();
- mCanvas->drawRoundRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
- radii.fX, radii.fY, paint);
+ mCanvas->drawRoundRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, radii.fX, radii.fY,
+ paint);
} else {
SkPath path;
path.addRRect(roundRect);
@@ -106,8 +106,8 @@ void SkiaCanvasProxy::onDrawRRect(const SkRRect& roundRect, const SkPaint& paint
void SkiaCanvasProxy::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
bool useCenter, const SkPaint& paint) {
- mCanvas->drawArc(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
- startAngle, sweepAngle, useCenter, paint);
+ mCanvas->drawArc(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, startAngle, sweepAngle,
+ useCenter, paint);
}
void SkiaCanvasProxy::onDrawPath(const SkPath& path, const SkPaint& paint) {
@@ -115,41 +115,38 @@ void SkiaCanvasProxy::onDrawPath(const SkPath& path, const SkPaint& paint) {
}
void SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint) {
+ const SkPaint* paint) {
sk_sp<Bitmap> hwuiBitmap = Bitmap::createFrom(bitmap.info(), *bitmap.pixelRef());
// HWUI doesn't support extractSubset(), so convert any subsetted bitmap into
// a drawBitmapRect(); pass through an un-subsetted bitmap.
if (hwuiBitmap && bitmap.dimensions() != hwuiBitmap->info().dimensions()) {
SkIPoint origin = bitmap.pixelRefOrigin();
- mCanvas->drawBitmap(*hwuiBitmap, origin.fX, origin.fY,
- origin.fX + bitmap.dimensions().width(),
- origin.fY + bitmap.dimensions().height(),
- left, top,
- left + bitmap.dimensions().width(),
- top + bitmap.dimensions().height(),
- paint);
+ mCanvas->drawBitmap(
+ *hwuiBitmap, origin.fX, origin.fY, origin.fX + bitmap.dimensions().width(),
+ origin.fY + bitmap.dimensions().height(), left, top,
+ left + bitmap.dimensions().width(), top + bitmap.dimensions().height(), paint);
} else {
mCanvas->drawBitmap(*hwuiBitmap, left, top, paint);
}
}
void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& skBitmap, const SkRect* srcPtr,
- const SkRect& dst, const SkPaint* paint, SrcRectConstraint) {
+ const SkRect& dst, const SkPaint* paint, SrcRectConstraint) {
SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(skBitmap.width(), skBitmap.height());
// TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
- Bitmap* bitmap = reinterpret_cast<Bitmap*>(skBitmap.pixelRef());
- mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
- dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+ Bitmap* bitmap = reinterpret_cast<Bitmap*>(skBitmap.pixelRef());
+ mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft, dst.fTop,
+ dst.fRight, dst.fBottom, paint);
}
void SkiaCanvasProxy::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint*) {
- //TODO make nine-patch drawing a method on Canvas.h
+ const SkRect& dst, const SkPaint*) {
+ // TODO make nine-patch drawing a method on Canvas.h
SkDEBUGFAIL("SkiaCanvasProxy::onDrawBitmapNine is not yet supported");
}
void SkiaCanvasProxy::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
- const SkPaint* paint) {
+ const SkPaint* paint) {
SkBitmap skiaBitmap;
SkPixmap pixmap;
if (image->peekPixels(&pixmap) && skiaBitmap.installPixels(pixmap)) {
@@ -158,33 +155,33 @@ void SkiaCanvasProxy::onDrawImage(const SkImage* image, SkScalar left, SkScalar
}
void SkiaCanvasProxy::onDrawImageRect(const SkImage* image, const SkRect* srcPtr, const SkRect& dst,
- const SkPaint* paint, SrcRectConstraint constraint) {
+ const SkPaint* paint, SrcRectConstraint constraint) {
SkBitmap skiaBitmap;
SkPixmap pixmap;
if (image->peekPixels(&pixmap) && skiaBitmap.installPixels(pixmap)) {
sk_sp<Bitmap> bitmap = Bitmap::createFrom(skiaBitmap.info(), *skiaBitmap.pixelRef());
SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(image->width(), image->height());
- mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
- dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+ mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft,
+ dst.fTop, dst.fRight, dst.fBottom, paint);
}
}
void SkiaCanvasProxy::onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
- const SkPaint*) {
+ const SkPaint*) {
SkDEBUGFAIL("SkiaCanvasProxy::onDrawImageNine is not yet supported");
}
void SkiaCanvasProxy::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
- const SkRect& dst, const SkPaint* paint) {
+ const SkRect& dst, const SkPaint* paint) {
SkLatticeIter iter(lattice, dst);
SkRect srcR, dstR;
while (iter.next(&srcR, &dstR)) {
- onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
+ onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kFast_SrcRectConstraint);
}
}
void SkiaCanvasProxy::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
- const SkPaint& paint) {
+ const SkPaint& paint) {
if (mFilterHwuiCalls) {
return;
}
@@ -207,14 +204,11 @@ static inline SaveFlags::Flags saveFlags(SkCanvas::SaveLayerFlags layerFlags) {
saveFlags |= SaveFlags::ClipToLayer;
}
- if (!(layerFlags & SkCanvas::kIsOpaque_SaveLayerFlag)) {
- saveFlags |= SaveFlags::HasAlphaLayer;
- }
-
return saveFlags;
}
-SkCanvas::SaveLayerStrategy SkiaCanvasProxy::getSaveLayerStrategy(const SaveLayerRec& saveLayerRec) {
+SkCanvas::SaveLayerStrategy SkiaCanvasProxy::getSaveLayerStrategy(
+ const SaveLayerRec& saveLayerRec) {
SkRect rect;
if (saveLayerRec.fBounds) {
rect = *saveLayerRec.fBounds;
@@ -239,7 +233,7 @@ void SkiaCanvasProxy::didSetMatrix(const SkMatrix& matrix) {
}
void SkiaCanvasProxy::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
- const SkPaint& paint) {
+ const SkPaint& paint) {
SkPath path;
path.addRRect(outer);
path.addRRect(inner);
@@ -259,7 +253,7 @@ public:
glyphIDs = (uint16_t*)text;
count = byteLength >> 1;
} else {
- // ensure space for one glyph per ID given UTF8 encoding.
+ // ensure space for one glyph per ID given UTF8 encoding.
storage.reset(new uint16_t[byteLength]);
glyphIDs = storage.get();
count = paint.textToGlyphs(text, byteLength, storage.get());
@@ -270,12 +264,13 @@ public:
SkPaint paint;
uint16_t* glyphIDs;
int count;
+
private:
std::unique_ptr<uint16_t[]> storage;
};
void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& origPaint) {
+ const SkPaint& origPaint) {
// convert to glyphIDs if necessary
GlyphIDConverter glyphs(text, byteLength, origPaint);
@@ -309,14 +304,14 @@ void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x
int xBaseline = 0;
int yBaseline = 0;
if (mCanvas->drawTextAbsolutePos()) {
- bounds.offset(x,y);
+ bounds.offset(x, y);
xBaseline = x;
yBaseline = y;
}
- static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
- auto glyphFunc = [&] (uint16_t* text, float* positions) {
- memcpy(text, glyphs.glyphIDs, glyphs.count*sizeof(uint16_t));
+ static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
+ auto glyphFunc = [&](uint16_t* text, float* positions) {
+ memcpy(text, glyphs.glyphIDs, glyphs.count * sizeof(uint16_t));
size_t posIndex = 0;
// setup the first glyph position
positions[posIndex++] = xBaseline;
@@ -326,24 +321,24 @@ void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x
float yPosition = yBaseline;
for (int i = 1; i < glyphs.count; i++) {
positions[posIndex++] = xBaseline;
- yPosition += glyphWidths[i-1];
+ yPosition += glyphWidths[i - 1];
positions[posIndex++] = yPosition;
}
} else {
float xPosition = xBaseline;
for (int i = 1; i < glyphs.count; i++) {
- xPosition += glyphWidths[i-1];
+ xPosition += glyphWidths[i - 1];
positions[posIndex++] = xPosition;
positions[posIndex++] = yBaseline;
}
}
};
mCanvas->drawGlyphs(glyphFunc, glyphs.count, glyphs.paint, x, y, bounds.fLeft, bounds.fTop,
- bounds.fRight, bounds.fBottom, 0);
+ bounds.fRight, bounds.fBottom, 0);
}
void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
- const SkPaint& origPaint) {
+ const SkPaint& origPaint) {
// convert to glyphIDs if necessary
GlyphIDConverter glyphs(text, byteLength, origPaint);
@@ -369,11 +364,11 @@ void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const S
bounds.join(glyphBounds);
}
- static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
- auto glyphFunc = [&] (uint16_t* text, float* positions) {
- memcpy(text, glyphs.glyphIDs, glyphs.count*sizeof(uint16_t));
+ static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
+ auto glyphFunc = [&](uint16_t* text, float* positions) {
+ memcpy(text, glyphs.glyphIDs, glyphs.count * sizeof(uint16_t));
if (mCanvas->drawTextAbsolutePos()) {
- memcpy(positions, pos, 2*glyphs.count*sizeof(float));
+ memcpy(positions, pos, 2 * glyphs.count * sizeof(float));
} else {
for (int i = 0, posIndex = 0; i < glyphs.count; i++) {
positions[posIndex++] = pos[i].fX - x;
@@ -382,11 +377,11 @@ void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const S
}
};
mCanvas->drawGlyphs(glyphFunc, glyphs.count, glyphs.paint, x, y, bounds.fLeft, bounds.fTop,
- bounds.fRight, bounds.fBottom, 0);
+ bounds.fRight, bounds.fBottom, 0);
}
void SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
- SkScalar constY, const SkPaint& paint) {
+ SkScalar constY, const SkPaint& paint) {
const size_t pointCount = byteLength >> 1;
std::unique_ptr<SkPoint[]> pts(new SkPoint[pointCount]);
for (size_t i = 0; i < pointCount; i++) {
@@ -396,13 +391,14 @@ void SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const
}
void SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
- const SkMatrix* matrix, const SkPaint& origPaint) {
+ const SkMatrix* matrix, const SkPaint& origPaint) {
SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextOnPath is not supported");
}
void SkiaCanvasProxy::onDrawTextRSXform(const void* text, size_t byteLength,
- const SkRSXform xform[], const SkRect* cullRect, const SkPaint& paint) {
- GlyphIDConverter glyphs(text, byteLength, paint); // Just get count
+ const SkRSXform xform[], const SkRect* cullRect,
+ const SkPaint& paint) {
+ GlyphIDConverter glyphs(text, byteLength, paint); // Just get count
SkMatrix localM, currM, origM;
mCanvas->getMatrix(&currM);
origM = currM;
@@ -410,55 +406,56 @@ void SkiaCanvasProxy::onDrawTextRSXform(const void* text, size_t byteLength,
localM.setRSXform(*xform++);
currM.setConcat(origM, localM);
mCanvas->setMatrix(currM);
- this->onDrawText((char*)text + (byteLength / glyphs.count * i),
- byteLength / glyphs.count, 0, 0, paint);
+ this->onDrawText((char*)text + (byteLength / glyphs.count * i), byteLength / glyphs.count,
+ 0, 0, paint);
}
mCanvas->setMatrix(origM);
}
-
void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
- const SkPaint& paint) {
+ const SkPaint& paint) {
SkPaint runPaint = paint;
- SkTextBlobRunIterator it(blob);
- for (;!it.done(); it.next()) {
- size_t textLen = it.glyphCount() * sizeof(uint16_t);
- const SkPoint& offset = it.offset();
- // applyFontToPaint() always overwrites the exact same attributes,
- // so it is safe to not re-seed the paint for this reason.
- it.applyFontToPaint(&runPaint);
-
- switch (it.positioning()) {
- case SkTextBlob::kDefault_Positioning:
- this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
- break;
- case SkTextBlob::kHorizontal_Positioning: {
- std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
- for (size_t i = 0; i < it.glyphCount(); i++) {
- pts[i].set(x + offset.x() + it.pos()[i], y + offset.y());
- }
- this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
- break;
- }
- case SkTextBlob::kFull_Positioning: {
- std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
- for (size_t i = 0; i < it.glyphCount(); i++) {
- const size_t xIndex = i*2;
- const size_t yIndex = xIndex + 1;
- pts[i].set(x + offset.x() + it.pos()[xIndex], y + offset.y() + it.pos()[yIndex]);
- }
- this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
- break;
- }
- default:
- SkFAIL("unhandled positioning mode");
- }
- }
+ SkTextBlobRunIterator it(blob);
+ for (; !it.done(); it.next()) {
+ size_t textLen = it.glyphCount() * sizeof(uint16_t);
+ const SkPoint& offset = it.offset();
+ // applyFontToPaint() always overwrites the exact same attributes,
+ // so it is safe to not re-seed the paint for this reason.
+ it.applyFontToPaint(&runPaint);
+
+ switch (it.positioning()) {
+ case SkTextBlob::kDefault_Positioning:
+ this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
+ break;
+ case SkTextBlob::kHorizontal_Positioning: {
+ std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
+ for (size_t i = 0; i < it.glyphCount(); i++) {
+ pts[i].set(x + offset.x() + it.pos()[i], y + offset.y());
+ }
+ this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
+ break;
+ }
+ case SkTextBlob::kFull_Positioning: {
+ std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
+ for (size_t i = 0; i < it.glyphCount(); i++) {
+ const size_t xIndex = i * 2;
+ const size_t yIndex = xIndex + 1;
+ pts[i].set(x + offset.x() + it.pos()[xIndex],
+ y + offset.y() + it.pos()[yIndex]);
+ }
+ this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
+ break;
+ }
+ default:
+ SK_ABORT("unhandled positioning mode");
+ }
+ }
}
void SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4], SkBlendMode bmode, const SkPaint& paint) {
+ const SkPoint texCoords[4], SkBlendMode bmode,
+ const SkPaint& paint) {
if (mFilterHwuiCalls) {
return;
}
@@ -466,9 +463,9 @@ void SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors
mCanvas->getMatrix(&matrix);
SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix);
- mCanvas->drawVertices(SkPatchUtils::MakeVertices(cubics, colors, texCoords,
- lod.width(), lod.height()).get(),
- bmode, paint);
+ mCanvas->drawVertices(
+ SkPatchUtils::MakeVertices(cubics, colors, texCoords, lod.width(), lod.height()).get(),
+ bmode, paint);
}
void SkiaCanvasProxy::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle) {
@@ -485,5 +482,5 @@ void SkiaCanvasProxy::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle)
mCanvas->clipPath(&path, op);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index d11a779b3600..360d5a08b974 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -17,8 +17,8 @@
#ifndef SkiaCanvasProxy_DEFINED
#define SkiaCanvasProxy_DEFINED
-#include <cutils/compiler.h>
#include <SkCanvas.h>
+#include <cutils/compiler.h>
#include "hwui/Canvas.h"
@@ -43,7 +43,6 @@ public:
virtual ~SkiaCanvasProxy() {}
protected:
-
virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
virtual void willSave() override;
@@ -66,15 +65,15 @@ protected:
const SkPaint*) override;
virtual void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint) override;
- virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint*) override;
+ virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
+ const SkPaint*) override;
virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
- SrcRectConstraint);
+ SrcRectConstraint);
virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
- const SkPaint*);
+ const SkPaint*);
virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
- const SkPaint*);
+ const SkPaint*);
virtual void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
@@ -107,7 +106,7 @@ private:
typedef SkCanvas INHERITED;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // SkiaCanvasProxy_DEFINED
+#endif // SkiaCanvasProxy_DEFINED
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 5c5378bf22ad..df746554f306 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -39,11 +39,11 @@ static constexpr GLenum gTileModes[] = {
};
static_assert(gTileModes[SkShader::kClamp_TileMode] == GL_CLAMP_TO_EDGE,
- "SkShader TileModes have changed");
+ "SkShader TileModes have changed");
static_assert(gTileModes[SkShader::kRepeat_TileMode] == GL_REPEAT,
- "SkShader TileModes have changed");
+ "SkShader TileModes have changed");
static_assert(gTileModes[SkShader::kMirror_TileMode] == GL_MIRRORED_REPEAT,
- "SkShader TileModes have changed");
+ "SkShader TileModes have changed");
/**
* This function does not work for n == 0.
@@ -70,7 +70,7 @@ static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, G
* @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
*/
static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
- const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
+ const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
mat4 shaderMatrix;
// uses implicit construction
shaderMatrix.loadInverse(localMatrix);
@@ -95,7 +95,7 @@ static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
}
static void toCircularUnitMatrix(const float x, const float y, const float radius,
- SkMatrix* matrix) {
+ SkMatrix* matrix) {
const float inv = 1.0f / radius;
matrix->setTranslate(-x, -y);
matrix->postScale(inv, inv);
@@ -118,8 +118,8 @@ static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
///////////////////////////////////////////////////////////////////////////////
bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 modelViewMatrix,
- GLuint* textureUnit, ProgramDescription* description,
- SkiaShaderData::GradientShaderData* outData) {
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData::GradientShaderData* outData) {
SkShader::GradientInfo gradInfo;
gradInfo.fColorCount = 0;
gradInfo.fColors = nullptr;
@@ -135,8 +135,8 @@ bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 mode
case SkShader::kRadial_GradientType:
description->gradientType = ProgramDescription::kGradientCircular;
- toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
- gradInfo.fRadius[0], &unitMatrix);
+ toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, gradInfo.fRadius[0],
+ &unitMatrix);
break;
case SkShader::kSweep_GradientType:
description->gradientType = ProgramDescription::kGradientSweep;
@@ -150,8 +150,8 @@ bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 mode
description->hasGradient = true;
description->isSimpleGradient = isSimpleGradient(gradInfo);
- computeScreenSpaceMatrix(outData->screenSpace, unitMatrix,
- shader.getLocalMatrix(), modelViewMatrix);
+ computeScreenSpaceMatrix(outData->screenSpace, unitMatrix, shader.getLocalMatrix(),
+ modelViewMatrix);
// re-query shader to get full color / offset data
std::unique_ptr<SkColor[]> colorStorage(new SkColor[gradInfo.fColorCount]);
@@ -164,7 +164,7 @@ bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 mode
outData->gradientSampler = (*textureUnit)++;
#ifndef SK_SCALAR_IS_FLOAT
- #error Need to convert gradInfo.fColorOffsets to float!
+#error Need to convert gradInfo.fColorOffsets to float!
#endif
outData->gradientTexture = caches.gradientCache.get(
gradInfo.fColors, gradInfo.fColorOffsets, gradInfo.fColorCount);
@@ -181,8 +181,7 @@ bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 mode
}
void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data,
- const GLsizei width, const GLsizei height) {
-
+ const GLsizei width, const GLsizei height) {
if (CC_UNLIKELY(data.gradientTexture)) {
caches.textureState().activateTexture(data.gradientSampler);
bindTexture(&caches, data.gradientTexture, data.wrapST, data.wrapST);
@@ -193,13 +192,13 @@ void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& dat
}
glUniform2f(caches.program().getUniform("screenSize"), 1.0f / width, 1.0f / height);
- glUniformMatrix4fv(caches.program().getUniform("screenSpace"), 1,
- GL_FALSE, &data.screenSpace.data[0]);
+ glUniformMatrix4fv(caches.program().getUniform("screenSpace"), 1, GL_FALSE,
+ &data.screenSpace.data[0]);
}
bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
- GLuint* textureUnit, ProgramDescription* description,
- SkiaShaderData::BitmapShaderData* outData) {
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData::BitmapShaderData* outData) {
SkBitmap bitmap;
SkShader::TileMode xy[2];
if (!shader.isABitmap(&bitmap, nullptr, xy)) {
@@ -225,9 +224,9 @@ bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& model
description->hasTranslucentConversion = texture->blend;
description->isShaderBitmapExternal = hwuiBitmap->isHardware();
// gralloc doesn't support non-clamp modes
- if (hwuiBitmap->isHardware() || (!caches.extensions().hasNPot()
- && (!isPowerOfTwo(width) || !isPowerOfTwo(height))
- && (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode))) {
+ if (hwuiBitmap->isHardware() ||
+ (!caches.extensions().hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
+ (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode))) {
// need non-clamp mode, but it's not supported for this draw,
// so enable custom shader logic to mimic
description->useShaderBasedWrap = true;
@@ -242,7 +241,7 @@ bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& model
}
computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
- modelViewMatrix);
+ modelViewMatrix);
outData->textureDimension[0] = 1.0f / width;
outData->textureDimension[1] = 1.0f / height;
@@ -256,7 +255,7 @@ void applyBitmap(Caches& caches, const SkiaShaderData::BitmapShaderData& data) {
glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler);
glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1, GL_FALSE,
- &data.textureTransform.data[0]);
+ &data.textureTransform.data[0]);
glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
}
@@ -283,20 +282,19 @@ SkiaShaderType getComposeSubType(const SkShader& shader) {
}
void storeCompose(Caches& caches, const SkShader& bitmapShader, const SkShader& gradientShader,
- const Matrix4& modelViewMatrix, GLuint* textureUnit,
- ProgramDescription* description, SkiaShaderData* outData) {
- LOG_ALWAYS_FATAL_IF(!tryStoreBitmap(caches, bitmapShader, modelViewMatrix,
- textureUnit, description, &outData->bitmapData),
- "failed storing bitmap shader data");
- LOG_ALWAYS_FATAL_IF(!tryStoreGradient(caches, gradientShader, modelViewMatrix,
- textureUnit, description, &outData->gradientData),
- "failing storing gradient shader data");
+ const Matrix4& modelViewMatrix, GLuint* textureUnit,
+ ProgramDescription* description, SkiaShaderData* outData) {
+ LOG_ALWAYS_FATAL_IF(!tryStoreBitmap(caches, bitmapShader, modelViewMatrix, textureUnit,
+ description, &outData->bitmapData),
+ "failed storing bitmap shader data");
+ LOG_ALWAYS_FATAL_IF(!tryStoreGradient(caches, gradientShader, modelViewMatrix, textureUnit,
+ description, &outData->gradientData),
+ "failing storing gradient shader data");
}
bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
- GLuint* textureUnit, ProgramDescription* description,
- SkiaShaderData* outData) {
-
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData* outData) {
SkShader::ComposeRec rec;
if (!shader.asACompose(&rec)) return false;
@@ -311,34 +309,33 @@ bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& mode
computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(), modelViewMatrix);
if (shaderAType == kBitmap_SkiaShaderType) {
description->isBitmapFirst = true;
- storeCompose(caches, *rec.fShaderA, *rec.fShaderB,
- transform, textureUnit, description, outData);
+ storeCompose(caches, *rec.fShaderA, *rec.fShaderB, transform, textureUnit, description,
+ outData);
} else {
description->isBitmapFirst = false;
- storeCompose(caches, *rec.fShaderB, *rec.fShaderA,
- transform, textureUnit, description, outData);
+ storeCompose(caches, *rec.fShaderB, *rec.fShaderA, transform, textureUnit, description,
+ outData);
}
description->shadersMode = rec.fBlendMode;
return true;
}
void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
- GLuint* textureUnit, ProgramDescription* description,
- SkiaShaderData* outData) {
- if (tryStoreGradient(caches, shader, modelViewMatrix,
- textureUnit, description, &outData->gradientData)) {
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData* outData) {
+ if (tryStoreGradient(caches, shader, modelViewMatrix, textureUnit, description,
+ &outData->gradientData)) {
outData->skiaShaderType = kGradient_SkiaShaderType;
return;
}
- if (tryStoreBitmap(caches, shader, modelViewMatrix,
- textureUnit, description, &outData->bitmapData)) {
+ if (tryStoreBitmap(caches, shader, modelViewMatrix, textureUnit, description,
+ &outData->bitmapData)) {
outData->skiaShaderType = kBitmap_SkiaShaderType;
return;
}
- if (tryStoreCompose(caches, shader, modelViewMatrix,
- textureUnit, description, outData)) {
+ if (tryStoreCompose(caches, shader, modelViewMatrix, textureUnit, description, outData)) {
outData->skiaShaderType = kCompose_SkiaShaderType;
return;
}
@@ -347,8 +344,8 @@ void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& mo
outData->skiaShaderType = kNone_SkiaShaderType;
}
-void SkiaShader::apply(Caches& caches, const SkiaShaderData& data,
- const GLsizei width, const GLsizei height) {
+void SkiaShader::apply(Caches& caches, const SkiaShaderData& data, const GLsizei width,
+ const GLsizei height) {
if (!data.skiaShaderType) return;
if (data.skiaShaderType & kGradient_SkiaShaderType) {
@@ -359,5 +356,5 @@ void SkiaShader::apply(Caches& caches, const SkiaShaderData& data,
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index ab578d540774..e8e92bdc1d76 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -74,13 +74,13 @@ struct SkiaShaderData {
class SkiaShader {
public:
static void store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
- GLuint* textureUnit, ProgramDescription* description,
- SkiaShaderData* outData);
- static void apply(Caches& caches, const SkiaShaderData& data,
- const GLsizei width, const GLsizei height);
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData* outData);
+ static void apply(Caches& caches, const SkiaShaderData& data, const GLsizei width,
+ const GLsizei height);
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_SKIA_SHADER_H
+#endif // ANDROID_HWUI_SKIA_SHADER_H
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 9d719bd1e997..f1a1bef7c94e 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -113,8 +113,8 @@ void Snapshot::resetClip(float left, float top, float right, float bottom) {
// Clipping round rect
///////////////////////////////////////////////////////////////////////////////
-void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
- float radius, bool highPriority) {
+void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius,
+ bool highPriority) {
if (bounds.isEmpty()) {
mClipArea->setEmpty();
return;
@@ -135,7 +135,7 @@ void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& boun
state->matrix.loadInverse(roundRectDrawingMatrix);
// compute area under rounded corners - only draws overlapping these rects need to be clipped
- for (int i = 0 ; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
state->dangerRects[i] = bounds;
}
state->dangerRects[0].bottom = state->dangerRects[1].bottom = bounds.top + radius;
@@ -170,15 +170,16 @@ static Snapshot* getClipRoot(Snapshot* target) {
}
const ClipBase* Snapshot::serializeIntersectedClip(LinearAllocator& allocator,
- const ClipBase* recordedClip, const Matrix4& recordedClipTransform) {
+ const ClipBase* recordedClip,
+ const Matrix4& recordedClipTransform) {
auto target = this;
if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
// Clip must be intersected with root, instead of current clip.
target = getClipRoot(this);
}
- return target->mClipArea->serializeIntersectedClip(allocator,
- recordedClip, recordedClipTransform);
+ return target->mClipArea->serializeIntersectedClip(allocator, recordedClip,
+ recordedClipTransform);
}
void Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform) {
@@ -194,15 +195,15 @@ void Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform)
///////////////////////////////////////////////////////////////////////////////
void Snapshot::dump() const {
- ALOGD("Snapshot %p, flags %x, prev %p, height %d, hasComplexClip %d",
- this, flags, previous, getViewportHeight(), !mClipArea->isSimple());
+ ALOGD("Snapshot %p, flags %x, prev %p, height %d, hasComplexClip %d", this, flags, previous,
+ getViewportHeight(), !mClipArea->isSimple());
const Rect& clipRect(mClipArea->getClipRect());
- ALOGD(" ClipRect %.1f %.1f %.1f %.1f, clip simple %d",
- clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, mClipArea->isSimple());
+ ALOGD(" ClipRect %.1f %.1f %.1f %.1f, clip simple %d", clipRect.left, clipRect.top,
+ clipRect.right, clipRect.bottom, mClipArea->isSimple());
ALOGD(" Transform (at %p):", transform);
transform->dump();
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 8cd90a68a9bb..655f819ca41b 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -19,9 +19,9 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <ui/Region.h>
#include <utils/LinearAllocator.h>
#include <utils/RefBase.h>
-#include <ui/Region.h>
#include <SkClipOp.h>
#include <SkRegion.h>
@@ -50,10 +50,8 @@ public:
}
bool areaRequiresRoundRectClip(const Rect& rect) const {
- return rect.intersects(dangerRects[0])
- || rect.intersects(dangerRects[1])
- || rect.intersects(dangerRects[2])
- || rect.intersects(dangerRects[3]);
+ return rect.intersects(dangerRects[0]) || rect.intersects(dangerRects[1]) ||
+ rect.intersects(dangerRects[2]) || rect.intersects(dangerRects[3]);
}
bool highPriority;
@@ -74,7 +72,6 @@ public:
*/
class Snapshot {
public:
-
Snapshot();
Snapshot(Snapshot* s, int saveFlags);
@@ -147,8 +144,9 @@ public:
const ClipArea& getClipArea() const { return *mClipArea; }
ClipArea& mutateClipArea() { return *mClipArea; }
- WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
- const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
+ WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(
+ LinearAllocator& allocator, const ClipBase* recordedClip,
+ const Matrix4& recordedClipTransform);
void applyClip(const ClipBase* clip, const Matrix4& transform);
/**
@@ -173,8 +171,8 @@ public:
*
* If the current round rect clip is high priority, the incoming clip is ignored.
*/
- void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
- float radius, bool highPriority);
+ void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius,
+ bool highPriority);
/**
* Sets (and replaces) the current projection mask
@@ -275,7 +273,7 @@ private:
ViewportData mViewportData;
Vector3 mRelativeLightCenter;
-}; // class Snapshot
+}; // class Snapshot
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 7b0a1bc3e93e..e371ac8da1e5 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -37,7 +37,7 @@
// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
// therefore, the maximum number of extra vertices will be twice bigger.
-#define SPOT_MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * SPOT_EXTRA_CORNER_VERTEX_PER_PI)
+#define SPOT_MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * SPOT_EXTRA_CORNER_VERTEX_PER_PI)
// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
#define SPOT_CORNER_RADIANS_DIVISOR (M_PI / SPOT_EXTRA_CORNER_VERTEX_PER_PI)
@@ -52,10 +52,10 @@
#include "VertexBuffer.h"
#include "utils/MathUtils.h"
-#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <utils/Log.h>
+#include <algorithm>
// TODO: After we settle down the new algorithm, we can remove the old one and
// its utility functions.
@@ -115,14 +115,14 @@ static float angle(const Vector2& point, const Vector2& center) {
* @param p2 The second point defining the line segment
* @return The distance along the ray if it intersects with the line segment, negative if otherwise
*/
-static float rayIntersectPoints(const Vector2& rayOrigin, float dx, float dy,
- const Vector2& p1, const Vector2& p2) {
+static float rayIntersectPoints(const Vector2& rayOrigin, float dx, float dy, const Vector2& p1,
+ const Vector2& p2) {
// The math below is derived from solving this formula, basically the
// intersection point should stay on both the ray and the edge of (p1, p2).
// solve([p1x+t*(p2x-p1x)=dx*t2+px,p1y+t*(p2y-p1y)=dy*t2+py],[t,t2]);
float divisor = (dx * (p1.y - p2.y) + dy * p2.x - dy * p1.x);
- if (divisor == 0) return -1.0f; // error, invalid divisor
+ if (divisor == 0) return -1.0f; // error, invalid divisor
#if DEBUG_SHADOW
float interpVal = (dx * (p1.y - rayOrigin.y) + dy * rayOrigin.x - dy * p1.x) / divisor;
@@ -132,9 +132,10 @@ static float rayIntersectPoints(const Vector2& rayOrigin, float dx, float dy,
#endif
float distance = (p1.x * (rayOrigin.y - p2.y) + p2.x * (p1.y - rayOrigin.y) +
- rayOrigin.x * (p2.y - p1.y)) / divisor;
+ rayOrigin.x * (p2.y - p1.y)) /
+ divisor;
- return distance; // may be negative in error cases
+ return distance; // may be negative in error cases
}
/**
@@ -144,9 +145,7 @@ static float rayIntersectPoints(const Vector2& rayOrigin, float dx, float dy,
* @param pointsLength the number of vertices of the polygon.
*/
void SpotShadow::xsort(Vector2* points, int pointsLength) {
- auto cmp = [](const Vector2& a, const Vector2& b) -> bool {
- return a.x < b.x;
- };
+ auto cmp = [](const Vector2& a, const Vector2& b) -> bool { return a.x < b.x; };
std::sort(points, points + pointsLength, cmp);
}
@@ -171,10 +170,9 @@ int SpotShadow::hull(Vector2* points, int pointsLength, Vector2* retPoly) {
lUpper[lUpperSize] = points[i];
lUpperSize++;
- while (lUpperSize > 2 && !ccw(
- lUpper[lUpperSize - 3].x, lUpper[lUpperSize - 3].y,
- lUpper[lUpperSize - 2].x, lUpper[lUpperSize - 2].y,
- lUpper[lUpperSize - 1].x, lUpper[lUpperSize - 1].y)) {
+ while (lUpperSize > 2 &&
+ !ccw(lUpper[lUpperSize - 3].x, lUpper[lUpperSize - 3].y, lUpper[lUpperSize - 2].x,
+ lUpper[lUpperSize - 2].y, lUpper[lUpperSize - 1].x, lUpper[lUpperSize - 1].y)) {
// Remove the middle point of the three last
lUpper[lUpperSize - 2].x = lUpper[lUpperSize - 1].x;
lUpper[lUpperSize - 2].y = lUpper[lUpperSize - 1].y;
@@ -192,10 +190,9 @@ int SpotShadow::hull(Vector2* points, int pointsLength, Vector2* retPoly) {
lLower[lLowerSize] = points[i];
lLowerSize++;
- while (lLowerSize > 2 && !ccw(
- lLower[lLowerSize - 3].x, lLower[lLowerSize - 3].y,
- lLower[lLowerSize - 2].x, lLower[lLowerSize - 2].y,
- lLower[lLowerSize - 1].x, lLower[lLowerSize - 1].y)) {
+ while (lLowerSize > 2 &&
+ !ccw(lLower[lLowerSize - 3].x, lLower[lLowerSize - 3].y, lLower[lLowerSize - 2].x,
+ lLower[lLowerSize - 2].y, lLower[lLowerSize - 1].x, lLower[lLowerSize - 1].y)) {
// Remove the middle point of the three last
lLower[lLowerSize - 2] = lLower[lLowerSize - 1];
lLowerSize--;
@@ -223,8 +220,7 @@ int SpotShadow::hull(Vector2* points, int pointsLength, Vector2* retPoly) {
*
* @return true if a right hand turn
*/
-bool SpotShadow::ccw(float ax, float ay, float bx, float by,
- float cx, float cy) {
+bool SpotShadow::ccw(float ax, float ay, float bx, float by, float cx, float cy) {
return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax) > EPSILON;
}
@@ -251,8 +247,7 @@ void SpotShadow::swap(Vector2* points, int i, int j) {
/**
* quick sort implementation about the center.
*/
-void SpotShadow::quicksortCirc(Vector2* points, int low, int high,
- const Vector2& center) {
+void SpotShadow::quicksortCirc(Vector2* points, int low, int high, const Vector2& center) {
int i = low, j = high;
int p = low + (high - low) / 2;
float pivot = angle(points[p], center);
@@ -281,8 +276,7 @@ void SpotShadow::quicksortCirc(Vector2* points, int low, int high,
* @param poly the polygon
* @return true if the testPoint is inside the poly.
*/
-bool SpotShadow::testPointInsidePolygon(const Vector2 testPoint,
- const Vector2* poly, int len) {
+bool SpotShadow::testPointInsidePolygon(const Vector2 testPoint, const Vector2* poly, int len) {
bool c = false;
float testx = testPoint.x;
float testy = testPoint.y;
@@ -292,9 +286,8 @@ bool SpotShadow::testPointInsidePolygon(const Vector2 testPoint,
float endX = poly[i].x;
float endY = poly[i].y;
- if (((endY > testy) != (startY > testy))
- && (testx < (startX - endX) * (testy - endY)
- / (startY - endY) + endX)) {
+ if (((endY > testy) != (startY > testy)) &&
+ (testx < (startX - endX) * (testy - endY) / (startY - endY) + endX)) {
c = !c;
}
}
@@ -326,8 +319,8 @@ void SpotShadow::reverse(Vector2* polygon, int len) {
* @param size the light size.
* @param ret result polygon.
*/
-void SpotShadow::computeLightPolygon(int points, const Vector3& lightCenter,
- float size, Vector3* ret) {
+void SpotShadow::computeLightPolygon(int points, const Vector3& lightCenter, float size,
+ Vector3* ret) {
// TODO: Caching all the sin / cos values and store them in a look up table.
for (int i = 0; i < points; i++) {
float angle = 2 * i * M_PI / points;
@@ -346,8 +339,8 @@ void SpotShadow::computeLightPolygon(int points, const Vector3& lightCenter,
*
* @return float The ratio of (polygon.z / light.z - polygon.z)
*/
-float SpotShadow::projectCasterToOutline(Vector2& outline,
- const Vector3& lightCenter, const Vector3& polyVertex) {
+float SpotShadow::projectCasterToOutline(Vector2& outline, const Vector3& lightCenter,
+ const Vector3& polyVertex) {
float lightToPolyZ = lightCenter.z - polyVertex.z;
float ratioZ = CASTER_Z_CAP_RATIO;
if (lightToPolyZ != 0) {
@@ -372,9 +365,9 @@ float SpotShadow::projectCasterToOutline(Vector2& outline,
* @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
* empty strip if error.
*/
-void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
- float lightSize, const Vector3* poly, int polyLength, const Vector3& polyCentroid,
- VertexBuffer& shadowTriangleStrip) {
+void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter, float lightSize,
+ const Vector3* poly, int polyLength, const Vector3& polyCentroid,
+ VertexBuffer& shadowTriangleStrip) {
if (CC_UNLIKELY(lightCenter.z <= 0)) {
ALOGW("Relative Light Z is not positive. No spot shadow!");
return;
@@ -403,21 +396,18 @@ void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCente
// Compute the last outline vertex to make sure we can get the normal and outline
// in one single loop.
- projectCasterToOutline(outlineData[polyLength - 1].position, lightCenter,
- poly[polyLength - 1]);
+ projectCasterToOutline(outlineData[polyLength - 1].position, lightCenter, poly[polyLength - 1]);
// Take the outline's polygon, calculate the normal for each outline edge.
int currentNormalIndex = polyLength - 1;
int nextNormalIndex = 0;
for (int i = 0; i < polyLength; i++) {
- float ratioZ = projectCasterToOutline(outlineData[i].position,
- lightCenter, poly[i]);
+ float ratioZ = projectCasterToOutline(outlineData[i].position, lightCenter, poly[i]);
outlineData[i].radius = ratioZ * lightSize;
outlineData[currentNormalIndex].normal = ShadowTessellator::calculateNormal(
- outlineData[currentNormalIndex].position,
- outlineData[nextNormalIndex].position);
+ outlineData[currentNormalIndex].position, outlineData[nextNormalIndex].position);
currentNormalIndex = (currentNormalIndex + 1) % polyLength;
nextNormalIndex++;
}
@@ -489,11 +479,9 @@ void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCente
(previousNormal * (currentCornerSliceNumber - k) + currentNormal * k) /
currentCornerSliceNumber;
avgNormal.normalize();
- penumbra[penumbraIndex++] = outlineData[i].position +
- avgNormal * outlineData[i].radius;
+ penumbra[penumbraIndex++] = outlineData[i].position + avgNormal * outlineData[i].radius;
}
-
// Compute the umbra by the intersection from the outline's centroid!
//
// (V) ------------------------------------
@@ -547,7 +535,7 @@ void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCente
#endif
for (int i = 0; i < polyLength; i++) {
umbra[i] = outlineData[i].position * FAKE_UMBRA_SIZE_RATIO +
- outlineCentroid * (1 - FAKE_UMBRA_SIZE_RATIO);
+ outlineCentroid * (1 - FAKE_UMBRA_SIZE_RATIO);
}
shadowStrengthScale = 1.0 / minRaitoVI;
}
@@ -556,7 +544,8 @@ void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCente
int umbraLength = polyLength;
#if DEBUG_SHADOW
- ALOGD("penumbraLength is %d , allocatedPenumbraLength %d", penumbraLength, allocatedPenumbraLength);
+ ALOGD("penumbraLength is %d , allocatedPenumbraLength %d", penumbraLength,
+ allocatedPenumbraLength);
dumpPolygon(poly, polyLength, "input poly");
dumpPolygon(penumbra, penumbraLength, "penumbra");
dumpPolygon(umbra, umbraLength, "umbra");
@@ -573,10 +562,9 @@ void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCente
int finalUmbraLength = hull(umbra, umbraLength, finalUmbra);
int finalPenumbraLength = hull(penumbra, penumbraLength, finalPenumbra);
- generateTriangleStrip(isCasterOpaque, shadowStrengthScale, finalPenumbra,
- finalPenumbraLength, finalUmbra, finalUmbraLength, poly, polyLength,
- shadowTriangleStrip, outlineCentroid);
-
+ generateTriangleStrip(isCasterOpaque, shadowStrengthScale, finalPenumbra, finalPenumbraLength,
+ finalUmbra, finalUmbraLength, poly, polyLength, shadowTriangleStrip,
+ outlineCentroid);
}
/**
@@ -632,7 +620,7 @@ inline int getClosestUmbraIndex(const Vector2& pivot, const Vector2* polygon, in
break;
}
}
- if(resultIndex == -1) {
+ if (resultIndex == -1) {
ALOGE("resultIndex is -1, the polygon must be invalid!");
resultIndex = 0;
}
@@ -651,7 +639,7 @@ inline bool sameDirections(bool isPositiveCross, float a, float b) {
// Find the right polygon edge to shoot the ray at.
inline int findPolyIndex(bool isPositiveCross, int startPolyIndex, const Vector2& umbraDir,
- const Vector2* polyToCentroid, int polyLength) {
+ const Vector2* polyToCentroid, int polyLength) {
// Make sure we loop with a bound.
for (int i = 0; i < polyLength; i++) {
int currentIndex = (i + startPolyIndex) % polyLength;
@@ -662,7 +650,7 @@ inline int findPolyIndex(bool isPositiveCross, int startPolyIndex, const Vector2
float umbraCrossNext = umbraDir.cross(nextToCentroid);
if (sameDirections(isPositiveCross, currentCrossUmbra, umbraCrossNext)) {
#if DEBUG_SHADOW
- ALOGD("findPolyIndex loop %d times , index %d", i, currentIndex );
+ ALOGD("findPolyIndex loop %d times , index %d", i, currentIndex);
#endif
return currentIndex;
}
@@ -674,12 +662,13 @@ inline int findPolyIndex(bool isPositiveCross, int startPolyIndex, const Vector2
// Generate the index pair for penumbra / umbra vertices, and more penumbra vertices
// if needed.
inline void genNewPenumbraAndPairWithUmbra(const Vector2* penumbra, int penumbraLength,
- const Vector2* umbra, int umbraLength, Vector2* newPenumbra, int& newPenumbraIndex,
- IndexPair* verticesPair, int& verticesPairIndex) {
+ const Vector2* umbra, int umbraLength,
+ Vector2* newPenumbra, int& newPenumbraIndex,
+ IndexPair* verticesPair, int& verticesPairIndex) {
// In order to keep everything in just one loop, we need to pre-compute the
// closest umbra vertex for the last penumbra vertex.
- int previousClosestUmbraIndex = getClosestUmbraIndex(penumbra[penumbraLength - 1],
- umbra, umbraLength);
+ int previousClosestUmbraIndex =
+ getClosestUmbraIndex(penumbra[penumbraLength - 1], umbra, umbraLength);
for (int i = 0; i < penumbraLength; i++) {
const Vector2& currentPenumbraVertex = penumbra[i];
// For current penumbra vertex, starting from previousClosestUmbraIndex,
@@ -704,7 +693,8 @@ inline void genNewPenumbraAndPairWithUmbra(const Vector2* penumbra, int penumbra
}
if (indexDelta > 1) {
- // For those umbra don't have penumbra, generate new penumbra vertices by interpolation.
+ // For those umbra don't have penumbra, generate new penumbra vertices by
+ // interpolation.
//
// Assuming Pi for penumbra vertices, and Ui for umbra vertices.
// In the case like below P1 paired with U1 and P2 paired with U5.
@@ -756,7 +746,7 @@ inline void genNewPenumbraAndPairWithUmbra(const Vector2* penumbra, int penumbra
float weightForPreviousPenumbra = 1.0f - weightForCurrentPenumbra;
Vector2 interpolatedPenumbra = currentPenumbraVertex * weightForCurrentPenumbra +
- previousPenumbra * weightForPreviousPenumbra;
+ previousPenumbra * weightForPreviousPenumbra;
int skippedUmbraIndex = (previousClosestUmbraIndex + k + 1) % umbraLength;
verticesPair[verticesPairIndex].outerIndex = newPenumbraIndex;
@@ -775,8 +765,8 @@ inline void genNewPenumbraAndPairWithUmbra(const Vector2* penumbra, int penumbra
}
// Precompute all the polygon's vector, return true if the reference cross product is positive.
-inline bool genPolyToCentroid(const Vector2* poly2d, int polyLength,
- const Vector2& centroid, Vector2* polyToCentroid) {
+inline bool genPolyToCentroid(const Vector2* poly2d, int polyLength, const Vector2& centroid,
+ Vector2* polyToCentroid) {
for (int j = 0; j < polyLength; j++) {
polyToCentroid[j] = poly2d[j] - centroid;
// Normalize these vectors such that we can use epsilon comparison after
@@ -798,21 +788,22 @@ inline bool genPolyToCentroid(const Vector2* poly2d, int polyLength,
// If the ray hit the polygon first, then return the intersection point as the
// closer vertex.
inline Vector2 getCloserVertex(const Vector2& umbraVertex, const Vector2& centroid,
- const Vector2* poly2d, int polyLength, const Vector2* polyToCentroid,
- bool isPositiveCross, int& previousPolyIndex) {
+ const Vector2* poly2d, int polyLength, const Vector2* polyToCentroid,
+ bool isPositiveCross, int& previousPolyIndex) {
Vector2 umbraToCentroid = umbraVertex - centroid;
float distanceToUmbra = umbraToCentroid.length();
umbraToCentroid = umbraToCentroid / distanceToUmbra;
// previousPolyIndex is updated for each item such that we can minimize the
// looping inside findPolyIndex();
- previousPolyIndex = findPolyIndex(isPositiveCross, previousPolyIndex,
- umbraToCentroid, polyToCentroid, polyLength);
+ previousPolyIndex = findPolyIndex(isPositiveCross, previousPolyIndex, umbraToCentroid,
+ polyToCentroid, polyLength);
float dx = umbraToCentroid.x;
float dy = umbraToCentroid.y;
- float distanceToIntersectPoly = rayIntersectPoints(centroid, dx, dy,
- poly2d[previousPolyIndex], poly2d[(previousPolyIndex + 1) % polyLength]);
+ float distanceToIntersectPoly =
+ rayIntersectPoints(centroid, dx, dy, poly2d[previousPolyIndex],
+ poly2d[(previousPolyIndex + 1) % polyLength]);
if (distanceToIntersectPoly < 0) {
distanceToIntersectPoly = 0;
}
@@ -833,9 +824,9 @@ inline Vector2 getCloserVertex(const Vector2& umbraVertex, const Vector2& centro
* Generate a triangle strip given two convex polygon
**/
void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale,
- Vector2* penumbra, int penumbraLength, Vector2* umbra, int umbraLength,
- const Vector3* poly, int polyLength, VertexBuffer& shadowTriangleStrip,
- const Vector2& centroid) {
+ Vector2* penumbra, int penumbraLength, Vector2* umbra,
+ int umbraLength, const Vector3* poly, int polyLength,
+ VertexBuffer& shadowTriangleStrip, const Vector2& centroid) {
bool hasOccludedUmbraArea = false;
Vector2 poly2d[polyLength];
@@ -891,7 +882,7 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength
// For each penumbra vertex, find its closet umbra vertex by comparing the
// neighbor umbra vertices.
genNewPenumbraAndPairWithUmbra(penumbra, penumbraLength, umbra, umbraLength, newPenumbra,
- newPenumbraIndex, verticesPair, verticesPairIndex);
+ newPenumbraIndex, verticesPair, verticesPairIndex);
ShadowTessellator::checkOverflow(verticesPairIndex, maxNewPenumbraLength, "Spot pair");
ShadowTessellator::checkOverflow(newPenumbraIndex, maxNewPenumbraLength, "Spot new penumbra");
#if DEBUG_SHADOW
@@ -915,17 +906,15 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength
const int newPenumbraLength = newPenumbraIndex;
const int totalVertexCount = newPenumbraLength + umbraLength * 2;
const int totalIndexCount = 2 * umbraLength + 2 * verticesPairIndex + 6;
- AlphaVertex* shadowVertices =
- shadowTriangleStrip.alloc<AlphaVertex>(totalVertexCount);
- uint16_t* indexBuffer =
- shadowTriangleStrip.allocIndices<uint16_t>(totalIndexCount);
+ AlphaVertex* shadowVertices = shadowTriangleStrip.alloc<AlphaVertex>(totalVertexCount);
+ uint16_t* indexBuffer = shadowTriangleStrip.allocIndices<uint16_t>(totalIndexCount);
int vertexBufferIndex = 0;
int indexBufferIndex = 0;
// Fill the IB and VB for the penumbra area.
for (int i = 0; i < newPenumbraLength; i++) {
- AlphaVertex::set(&shadowVertices[vertexBufferIndex++], newPenumbra[i].x,
- newPenumbra[i].y, PENUMBRA_ALPHA);
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], newPenumbra[i].x, newPenumbra[i].y,
+ PENUMBRA_ALPHA);
}
// Since the umbra can be a faked one when the occluder is too high, the umbra should be lighter
// in this case.
@@ -933,7 +922,7 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength
for (int i = 0; i < umbraLength; i++) {
AlphaVertex::set(&shadowVertices[vertexBufferIndex++], umbra[i].x, umbra[i].y,
- scaledUmbraAlpha);
+ scaledUmbraAlpha);
}
for (int i = 0; i < verticesPairIndex; i++) {
@@ -966,21 +955,22 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength
for (int i = 0; i < umbraLength; i++) {
// Shoot a ray from centroid to each umbra vertices and pick the one with
// shorter distance to the centroid, b/t the umbra vertex or the intersection point.
- Vector2 closerVertex = getCloserVertex(umbra[i], centroid, poly2d, polyLength,
- polyToCentroid, isPositiveCross, previousPolyIndex);
+ Vector2 closerVertex =
+ getCloserVertex(umbra[i], centroid, poly2d, polyLength, polyToCentroid,
+ isPositiveCross, previousPolyIndex);
// We already stored the umbra vertices, just need to add the occlued umbra's ones.
indexBuffer[indexBufferIndex++] = newPenumbraLength + i;
indexBuffer[indexBufferIndex++] = vertexBufferIndex;
- AlphaVertex::set(&shadowVertices[vertexBufferIndex++],
- closerVertex.x, closerVertex.y, scaledUmbraAlpha);
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], closerVertex.x, closerVertex.y,
+ scaledUmbraAlpha);
}
} else {
// If there is no occluded umbra at all, then draw the triangle fan
// starting from the centroid to all umbra vertices.
int lastCentroidIndex = vertexBufferIndex;
- AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid.x,
- centroid.y, scaledUmbraAlpha);
+ AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid.x, centroid.y,
+ scaledUmbraAlpha);
for (int i = 0; i < umbraLength; i++) {
indexBuffer[indexBufferIndex++] = newPenumbraLength + i;
indexBuffer[indexBufferIndex++] = lastCentroidIndex;
@@ -1006,8 +996,7 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength
/**
* Calculate the bounds for generating random test points.
*/
-void SpotShadow::updateBound(const Vector2 inVector, Vector2& lowerBound,
- Vector2& upperBound) {
+void SpotShadow::updateBound(const Vector2 inVector, Vector2& lowerBound, Vector2& upperBound) {
if (inVector.x < lowerBound.x) {
lowerBound.x = inVector.x;
}
@@ -1046,8 +1035,7 @@ void SpotShadow::dumpPolygon(const Vector3* poly, int polyLength, const char* po
/**
* Test whether the polygon is convex.
*/
-bool SpotShadow::testConvex(const Vector2* polygon, int polygonLength,
- const char* name) {
+bool SpotShadow::testConvex(const Vector2* polygon, int polygonLength, const char* name) {
bool isConvex = true;
for (int i = 0; i < polygonLength; i++) {
Vector2 start = polygon[i];
@@ -1055,13 +1043,13 @@ bool SpotShadow::testConvex(const Vector2* polygon, int polygonLength,
Vector2 end = polygon[(i + 2) % polygonLength];
float delta = (float(middle.x) - start.x) * (float(end.y) - start.y) -
- (float(middle.y) - start.y) * (float(end.x) - start.x);
+ (float(middle.y) - start.y) * (float(end.x) - start.x);
bool isCCWOrCoLinear = (delta >= EPSILON);
if (isCCWOrCoLinear) {
ALOGW("(Error Type 2): polygon (%s) is not a convex b/c start (x %f, y %f),"
- "middle (x %f, y %f) and end (x %f, y %f) , delta is %f !!!",
- name, start.x, start.y, middle.x, middle.y, end.x, end.y, delta);
+ "middle (x %f, y %f) and end (x %f, y %f) , delta is %f !!!",
+ name, start.x, start.y, middle.x, middle.y, end.x, end.y, delta);
isConvex = false;
break;
}
@@ -1074,9 +1062,9 @@ bool SpotShadow::testConvex(const Vector2* polygon, int polygonLength,
* Using Marte Carlo method, we generate a random point, and if it is inside the
* intersection, then it must be inside both source polygons.
*/
-void SpotShadow::testIntersection(const Vector2* poly1, int poly1Length,
- const Vector2* poly2, int poly2Length,
- const Vector2* intersection, int intersectionLength) {
+void SpotShadow::testIntersection(const Vector2* poly1, int poly1Length, const Vector2* poly2,
+ int poly2Length, const Vector2* intersection,
+ int intersectionLength) {
// Find the min and max of x and y.
Vector2 lowerBound = {FLT_MAX, FLT_MAX};
Vector2 upperBound = {-FLT_MAX, -FLT_MAX};
@@ -1102,15 +1090,15 @@ void SpotShadow::testIntersection(const Vector2* poly1, int poly1Length,
if (!testPointInsidePolygon(testPoint, poly1, poly1Length)) {
dumpPoly = true;
ALOGW("(Error Type 1): one point (%f, %f) in the intersection is"
- " not in the poly1",
- testPoint.x, testPoint.y);
+ " not in the poly1",
+ testPoint.x, testPoint.y);
}
if (!testPointInsidePolygon(testPoint, poly2, poly2Length)) {
dumpPoly = true;
ALOGW("(Error Type 1): one point (%f, %f) in the intersection is"
- " not in the poly2",
- testPoint.x, testPoint.y);
+ " not in the poly2",
+ testPoint.x, testPoint.y);
}
}
}
@@ -1128,5 +1116,5 @@ void SpotShadow::testIntersection(const Vector2* poly1, int poly1Length,
}
#endif
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h
index 6108bb6bd585..8476be70318b 100644
--- a/libs/hwui/SpotShadow.h
+++ b/libs/hwui/SpotShadow.h
@@ -27,22 +27,22 @@ class VertexBuffer;
class SpotShadow {
public:
- static void createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
- float lightSize, const Vector3* poly, int polyLength,
- const Vector3& polyCentroid, VertexBuffer& retstrips);
+ static void createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter, float lightSize,
+ const Vector3* poly, int polyLength, const Vector3& polyCentroid,
+ VertexBuffer& retstrips);
private:
struct VertexAngleData;
- static float projectCasterToOutline(Vector2& outline,
- const Vector3& lightCenter, const Vector3& polyVertex);
+ static float projectCasterToOutline(Vector2& outline, const Vector3& lightCenter,
+ const Vector3& polyVertex);
- static void computeLightPolygon(int points, const Vector3& lightCenter,
- float size, Vector3* ret);
+ static void computeLightPolygon(int points, const Vector3& lightCenter, float size,
+ Vector3* ret);
static void smoothPolygon(int level, int rays, float* rayDist);
- static float rayIntersectPoly(const Vector2* poly, int polyLength,
- const Vector2& point, float dx, float dy);
+ static float rayIntersectPoly(const Vector2* poly, int polyLength, const Vector2& point,
+ float dx, float dy);
static void xsort(Vector2* points, int pointsLength);
static int hull(Vector2* points, int pointsLength, Vector2* retPoly);
@@ -57,23 +57,23 @@ private:
static void reverse(Vector2* polygon, int len);
static void generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale,
- Vector2* penumbra, int penumbraLength, Vector2* umbra, int umbraLength,
- const Vector3* poly, int polyLength, VertexBuffer& retstrips, const Vector2& centroid);
+ Vector2* penumbra, int penumbraLength, Vector2* umbra,
+ int umbraLength, const Vector3* poly, int polyLength,
+ VertexBuffer& retstrips, const Vector2& centroid);
#if DEBUG_SHADOW
- static bool testConvex(const Vector2* polygon, int polygonLength,
- const char* name);
- static void testIntersection(const Vector2* poly1, int poly1Length,
- const Vector2* poly2, int poly2Length,
- const Vector2* intersection, int intersectionLength);
- static void updateBound(const Vector2 inVector, Vector2& lowerBound, Vector2& upperBound );
+ static bool testConvex(const Vector2* polygon, int polygonLength, const char* name);
+ static void testIntersection(const Vector2* poly1, int poly1Length, const Vector2* poly2,
+ int poly2Length, const Vector2* intersection,
+ int intersectionLength);
+ static void updateBound(const Vector2 inVector, Vector2& lowerBound, Vector2& upperBound);
static void dumpPolygon(const Vector2* poly, int polyLength, const char* polyName);
static void dumpPolygon(const Vector3* poly, int polyLength, const char* polyName);
#endif
-}; // SpotShadow
+}; // SpotShadow
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_SPOT_SHADOW_H
+#endif // ANDROID_HWUI_SPOT_SHADOW_H
diff --git a/libs/hwui/SwapBehavior.h b/libs/hwui/SwapBehavior.h
new file mode 100644
index 000000000000..3a176d7bfbcc
--- /dev/null
+++ b/libs/hwui/SwapBehavior.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HWUI_SWAPBEHAVIOR_H
+#define HWUI_SWAPBEHAVIOR_H
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+enum class SwapBehavior {
+ kSwap_default,
+ kSwap_discardBuffer,
+};
+
+} // namespace renderthread
+} // namespace uirenderer
+} // namespace android
+
+#endif // HWUI_SWAPBEHAVIOR_H
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 63bf7bc443e0..c7d93da718e7 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -45,7 +45,8 @@ TessellationCache::Description::Description()
memset(&shape, 0, sizeof(Shape));
}
-TessellationCache::Description::Description(Type type, const Matrix4& transform, const SkPaint& paint)
+TessellationCache::Description::Description(Type type, const Matrix4& transform,
+ const SkPaint& paint)
: type(type)
, aa(paint.isAntiAlias())
, cap(paint.getStrokeCap())
@@ -82,7 +83,7 @@ hash_t TessellationCache::Description::hash() const {
hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
hash = JenkinsHashMix(hash, android::hash_type(scaleX));
hash = JenkinsHashMix(hash, android::hash_type(scaleY));
- hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape));
+ hash = JenkinsHashMixBytes(hash, (uint8_t*)&shape, sizeof(Shape));
return JenkinsHashWhiten(hash);
}
@@ -94,25 +95,24 @@ void TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPain
paint->setStrokeWidth(strokeWidth);
}
-TessellationCache::ShadowDescription::ShadowDescription()
- : nodeKey(nullptr) {
+TessellationCache::ShadowDescription::ShadowDescription() : nodeKey(nullptr) {
memset(&matrixData, 0, sizeof(matrixData));
}
-TessellationCache::ShadowDescription::ShadowDescription(const SkPath* nodeKey, const Matrix4* drawTransform)
+TessellationCache::ShadowDescription::ShadowDescription(const SkPath* nodeKey,
+ const Matrix4* drawTransform)
: nodeKey(nodeKey) {
memcpy(&matrixData, drawTransform->data, sizeof(matrixData));
}
bool TessellationCache::ShadowDescription::operator==(
const TessellationCache::ShadowDescription& rhs) const {
- return nodeKey == rhs.nodeKey
- && memcmp(&matrixData, &rhs.matrixData, sizeof(matrixData)) == 0;
+ return nodeKey == rhs.nodeKey && memcmp(&matrixData, &rhs.matrixData, sizeof(matrixData)) == 0;
}
hash_t TessellationCache::ShadowDescription::hash() const {
- uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*) &nodeKey, sizeof(const void*));
- hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, sizeof(matrixData));
+ uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*)&nodeKey, sizeof(const void*));
+ hash = JenkinsHashMixBytes(hash, (uint8_t*)&matrixData, sizeof(matrixData));
return JenkinsHashWhiten(hash);
}
@@ -123,9 +123,7 @@ hash_t TessellationCache::ShadowDescription::hash() const {
class TessellationCache::TessellationTask : public Task<VertexBuffer*> {
public:
TessellationTask(Tessellator tessellator, const Description& description)
- : tessellator(tessellator)
- , description(description) {
- }
+ : tessellator(tessellator), description(description) {}
~TessellationTask() {}
@@ -135,8 +133,7 @@ public:
class TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> {
public:
- explicit TessellationProcessor(Caches& caches)
- : TaskProcessor<VertexBuffer*>(&caches.tasks) {}
+ explicit TessellationProcessor(Caches& caches) : TaskProcessor<VertexBuffer*>(&caches.tasks) {}
~TessellationProcessor() {}
virtual void onProcess(const sp<Task<VertexBuffer*> >& task) override {
@@ -149,10 +146,7 @@ public:
class TessellationCache::Buffer {
public:
- explicit Buffer(const sp<Task<VertexBuffer*> >& task)
- : mTask(task)
- , mBuffer(nullptr) {
- }
+ explicit Buffer(const sp<Task<VertexBuffer*> >& task) : mTask(task), mBuffer(nullptr) {}
~Buffer() {
mTask.clear();
@@ -203,18 +197,15 @@ static void reverseVertexArray(Vertex* polygon, int len) {
}
}
-void tessellateShadows(
- const Matrix4* drawTransform, const Rect* localClip,
- bool isCasterOpaque, const SkPath* casterPerimeter,
- const Matrix4* casterTransformXY, const Matrix4* casterTransformZ,
- const Vector3& lightCenter, float lightRadius,
- VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer) {
-
+void tessellateShadows(const Matrix4* drawTransform, const Rect* localClip, bool isCasterOpaque,
+ const SkPath* casterPerimeter, const Matrix4* casterTransformXY,
+ const Matrix4* casterTransformZ, const Vector3& lightCenter,
+ float lightRadius, VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer) {
// tessellate caster outline into a 2d polygon
std::vector<Vertex> casterVertices2d;
const float casterRefinementThreshold = 2.0f;
- PathTessellator::approximatePathOutlineVertices(*casterPerimeter,
- casterRefinementThreshold, casterVertices2d);
+ PathTessellator::approximatePathOutlineVertices(*casterPerimeter, casterRefinementThreshold,
+ casterVertices2d);
// Shadow requires CCW for now. TODO: remove potential double-reverse
reverseVertexArray(&casterVertices2d.front(), casterVertices2d.size());
@@ -235,9 +226,8 @@ void tessellateShadows(
}
// map the centroid of the caster into 3d
- Vector2 centroid = ShadowTessellator::centroid2d(
- reinterpret_cast<const Vector2*>(&casterVertices2d.front()),
- casterVertexCount);
+ Vector2 centroid = ShadowTessellator::centroid2d(
+ reinterpret_cast<const Vector2*>(&casterVertices2d.front()), casterVertexCount);
Vector3 centroid3d = {centroid.x, centroid.y, 0};
mapPointFakeZ(centroid3d, casterTransformXY, casterTransformZ);
@@ -257,14 +247,13 @@ void tessellateShadows(
casterTransformXY->mapRect(casterBounds);
// actual tessellation of both shadows
- ShadowTessellator::tessellateAmbientShadow(
- isCasterOpaque, casterPolygon, casterVertexCount, centroid3d,
- casterBounds, *localClip, maxZ, ambientBuffer);
-
- ShadowTessellator::tessellateSpotShadow(
- isCasterOpaque, casterPolygon, casterVertexCount, centroid3d,
- *drawTransform, lightCenter, lightRadius, casterBounds, *localClip,
- spotBuffer);
+ ShadowTessellator::tessellateAmbientShadow(isCasterOpaque, casterPolygon, casterVertexCount,
+ centroid3d, casterBounds, *localClip, maxZ,
+ ambientBuffer);
+
+ ShadowTessellator::tessellateSpotShadow(isCasterOpaque, casterPolygon, casterVertexCount,
+ centroid3d, *drawTransform, lightCenter, lightRadius,
+ casterBounds, *localClip, spotBuffer);
}
class ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t> {
@@ -278,8 +267,8 @@ public:
ATRACE_NAME("shadow tessellation");
tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter,
- &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius,
- t->ambientBuffer, t->spotBuffer);
+ &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius,
+ t->ambientBuffer, t->spotBuffer);
t->setResult(TessellationCache::vertexBuffer_pair_t(&t->ambientBuffer, &t->spotBuffer));
}
@@ -292,7 +281,8 @@ public:
TessellationCache::TessellationCache()
: mMaxSize(MB(1))
, mCache(LruCache<Description, Buffer*>::kUnlimitedCapacity)
- , mShadowCache(LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) {
+ , mShadowCache(
+ LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) {
mCache.setOnEntryRemovedListener(&mBufferRemovedListener);
mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener);
mDebugEnabled = Properties::debugLevel & kDebugCaches;
@@ -323,7 +313,6 @@ uint32_t TessellationCache::getMaxSize() {
// Caching
///////////////////////////////////////////////////////////////////////////////
-
void TessellationCache::trim() {
uint32_t size = getSize();
while (size > mMaxSize) {
@@ -343,7 +332,7 @@ void TessellationCache::clear() {
///////////////////////////////////////////////////////////////////////////////
void TessellationCache::BufferRemovedListener::operator()(Description& description,
- Buffer*& buffer) {
+ Buffer*& buffer) {
delete buffer;
}
@@ -352,32 +341,31 @@ void TessellationCache::BufferRemovedListener::operator()(Description& descripti
///////////////////////////////////////////////////////////////////////////////
void TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius) {
+ bool opaque, const SkPath* casterPerimeter,
+ const Matrix4* transformXY, const Matrix4* transformZ,
+ const Vector3& lightCenter, float lightRadius) {
ShadowDescription key(casterPerimeter, drawTransform);
if (mShadowCache.get(key)) return;
- sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque,
- casterPerimeter, transformXY, transformZ, lightCenter, lightRadius);
+ sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque, casterPerimeter,
+ transformXY, transformZ, lightCenter, lightRadius);
if (mShadowProcessor == nullptr) {
mShadowProcessor = new ShadowProcessor(Caches::getInstance());
}
mShadowProcessor->add(task);
- task->incStrong(nullptr); // not using sp<>s, so manually ref while in the cache
+ task->incStrong(nullptr); // not using sp<>s, so manually ref while in the cache
mShadowCache.put(key, task.get());
}
sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask(
- const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
+ const Matrix4* drawTransform, const Rect& localClip, bool opaque,
+ const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
const Vector3& lightCenter, float lightRadius) {
ShadowDescription key(casterPerimeter, drawTransform);
ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key));
if (!task) {
- precacheShadows(drawTransform, localClip, opaque, casterPerimeter,
- transformXY, transformZ, lightCenter, lightRadius);
+ precacheShadows(drawTransform, localClip, opaque, casterPerimeter, transformXY, transformZ,
+ lightCenter, lightRadius);
task = static_cast<ShadowTask*>(mShadowCache.get(key));
}
LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached");
@@ -388,8 +376,8 @@ sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask(
// Tessellation precaching
///////////////////////////////////////////////////////////////////////////////
-TessellationCache::Buffer* TessellationCache::getOrCreateBuffer(
- const Description& entry, Tessellator tessellator) {
+TessellationCache::Buffer* TessellationCache::getOrCreateBuffer(const Description& entry,
+ Tessellator tessellator) {
Buffer* buffer = mCache.get(entry);
if (!buffer) {
// not cached, enqueue a task to fill the buffer
@@ -408,7 +396,7 @@ TessellationCache::Buffer* TessellationCache::getOrCreateBuffer(
}
static VertexBuffer* tessellatePath(const TessellationCache::Description& description,
- const SkPath& path) {
+ const SkPath& path) {
Matrix4 matrix;
SkPaint paint;
description.setupMatrixAndPaint(&matrix, &paint);
@@ -422,8 +410,8 @@ static VertexBuffer* tessellatePath(const TessellationCache::Description& descri
///////////////////////////////////////////////////////////////////////////////
static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description) {
- SkRect rect = SkRect::MakeWH(description.shape.roundRect.width,
- description.shape.roundRect.height);
+ SkRect rect =
+ SkRect::MakeWH(description.shape.roundRect.width, description.shape.roundRect.height);
float rx = description.shape.roundRect.rx;
float ry = description.shape.roundRect.ry;
if (description.style == SkPaint::kStrokeAndFill_Style) {
@@ -437,9 +425,9 @@ static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& d
return tessellatePath(description, path);
}
-TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(
- const Matrix4& transform, const SkPaint& paint,
- float width, float height, float rx, float ry) {
+TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform,
+ const SkPaint& paint, float width,
+ float height, float rx, float ry) {
Description entry(Description::Type::RoundRect, transform, paint);
entry.shape.roundRect.width = width;
entry.shape.roundRect.height = height;
@@ -448,9 +436,9 @@ TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(
return getOrCreateBuffer(entry, &tessellateRoundRect);
}
const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, const SkPaint& paint,
- float width, float height, float rx, float ry) {
+ float width, float height, float rx, float ry) {
return getRoundRectBuffer(transform, paint, width, height, rx, ry)->getVertexBuffer();
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index ccad1b7bd415..a0f0ed4653e0 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -90,17 +90,16 @@ public:
class ShadowTask : public Task<vertexBuffer_pair_t> {
public:
ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
- const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius)
- : drawTransform(*drawTransform)
- , localClip(localClip)
- , opaque(opaque)
- , casterPerimeter(*casterPerimeter)
- , transformXY(*transformXY)
- , transformZ(*transformZ)
- , lightCenter(lightCenter)
- , lightRadius(lightRadius) {
- }
+ const SkPath* casterPerimeter, const Matrix4* transformXY,
+ const Matrix4* transformZ, const Vector3& lightCenter, float lightRadius)
+ : drawTransform(*drawTransform)
+ , localClip(localClip)
+ , opaque(opaque)
+ , casterPerimeter(*casterPerimeter)
+ , transformXY(*transformXY)
+ , transformZ(*transformZ)
+ , lightCenter(lightCenter)
+ , lightRadius(lightRadius) {}
/* Note - we deep copy all task parameters, because *even though* pointers into Allocator
* controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
@@ -153,17 +152,17 @@ public:
// TODO: precache/get for Oval, Lines, Points, etc.
- void precacheRoundRect(const Matrix4& transform, const SkPaint& paint,
- float width, float height, float rx, float ry) {
+ void precacheRoundRect(const Matrix4& transform, const SkPaint& paint, float width,
+ float height, float rx, float ry) {
getRoundRectBuffer(transform, paint, width, height, rx, ry);
}
- const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
- float width, float height, float rx, float ry);
+ const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint, float width,
+ float height, float rx, float ry);
- sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius);
+ sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
+ const SkPath* casterPerimeter, const Matrix4* transformXY,
+ const Matrix4* transformZ, const Vector3& lightCenter,
+ float lightRadius);
private:
class Buffer;
@@ -172,15 +171,14 @@ private:
typedef VertexBuffer* (*Tessellator)(const Description&);
- void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius);
+ void precacheShadows(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
+ const SkPath* casterPerimeter, const Matrix4* transformXY,
+ const Matrix4* transformZ, const Vector3& lightCenter, float lightRadius);
- Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint,
- float width, float height);
- Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint,
- float width, float height, float rx, float ry);
+ Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint, float width,
+ float height);
+ Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint, float width,
+ float height, float rx, float ry);
Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator);
@@ -207,21 +205,21 @@ private:
// holds a pointer, and implicit strong ref to each shadow task of the frame
LruCache<ShadowDescription, Task<vertexBuffer_pair_t>*> mShadowCache;
- class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t>*> {
- void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t>*& bufferPairTask) override {
+ class BufferPairRemovedListener
+ : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t>*> {
+ void operator()(ShadowDescription& description,
+ Task<vertexBuffer_pair_t>*& bufferPairTask) override {
bufferPairTask->decStrong(nullptr);
}
};
BufferPairRemovedListener mBufferPairRemovedListener;
-}; // class TessellationCache
+}; // class TessellationCache
-void tessellateShadows(
- const Matrix4* drawTransform, const Rect* localClip,
- bool isCasterOpaque, const SkPath* casterPerimeter,
- const Matrix4* casterTransformXY, const Matrix4* casterTransformZ,
- const Vector3& lightCenter, float lightRadius,
- VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer);
+void tessellateShadows(const Matrix4* drawTransform, const Rect* localClip, bool isCasterOpaque,
+ const SkPath* casterPerimeter, const Matrix4* casterTransformXY,
+ const Matrix4* casterTransformZ, const Vector3& lightCenter,
+ float lightRadius, VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer);
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index c521892c69df..c892ceb3e14d 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -19,8 +19,8 @@
#include "Caches.h"
#include "Debug.h"
#include "FontRenderer.h"
-#include "TextDropShadowCache.h"
#include "Properties.h"
+#include "TextDropShadowCache.h"
namespace android {
namespace uirenderer {
@@ -38,8 +38,7 @@ hash_t ShadowText::hash() const {
hash = JenkinsHashMix(hash, android::hash_type(italicStyle));
hash = JenkinsHashMix(hash, android::hash_type(scaleX));
if (glyphs) {
- hash = JenkinsHashMixShorts(
- hash, reinterpret_cast<const uint16_t*>(glyphs), glyphCount);
+ hash = JenkinsHashMixShorts(hash, reinterpret_cast<const uint16_t*>(glyphs), glyphCount);
}
if (positions) {
for (uint32_t i = 0; i < glyphCount * 2; i++) {
@@ -146,15 +145,15 @@ void TextDropShadowCache::clear() {
}
ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
- float radius, const float* positions) {
+ float radius, const float* positions) {
ShadowText entry(paint, radius, numGlyphs, glyphs, positions);
ShadowTexture* texture = mCache.get(entry);
if (!texture) {
SkPaint paintCopy(*paint);
paintCopy.setTextAlign(SkPaint::kLeft_Align);
- FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(&paintCopy, glyphs, numGlyphs,
- radius, positions);
+ FontRenderer::DropShadow shadow =
+ mRenderer->renderDropShadow(&paintCopy, glyphs, numGlyphs, radius, positions);
if (!shadow.image) {
return nullptr;
@@ -174,14 +173,15 @@ ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const glyph_t* gly
if (size < mMaxSize) {
while (mSize + size > mMaxSize) {
LOG_ALWAYS_FATAL_IF(!mCache.removeOldest(),
- "Failed to remove oldest from cache. mSize = %"
- PRIu32 ", mCache.size() = %zu", mSize, mCache.size());
+ "Failed to remove oldest from cache. mSize = %" PRIu32
+ ", mCache.size() = %zu",
+ mSize, mCache.size());
}
}
// Textures are Alpha8
- texture->upload(GL_ALPHA, shadow.width, shadow.height,
- GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image);
+ texture->upload(GL_ALPHA, shadow.width, shadow.height, GL_ALPHA, GL_UNSIGNED_BYTE,
+ shadow.image);
texture->setFilter(GL_LINEAR);
texture->setWrap(GL_CLAMP_TO_EDGE);
@@ -205,5 +205,5 @@ ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const glyph_t* gly
return texture;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 13e87749029a..86a012970f17 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -24,8 +24,8 @@
#include <utils/LruCache.h>
#include <utils/String16.h>
-#include "font/Font.h"
#include "Texture.h"
+#include "font/Font.h"
namespace android {
namespace uirenderer {
@@ -34,13 +34,20 @@ class Caches;
class FontRenderer;
struct ShadowText {
- ShadowText(): glyphCount(0), radius(0.0f), textSize(0.0f), typeface(nullptr),
- flags(0), italicStyle(0.0f), scaleX(0), glyphs(nullptr), positions(nullptr) {
- }
+ ShadowText()
+ : glyphCount(0)
+ , radius(0.0f)
+ , textSize(0.0f)
+ , typeface(nullptr)
+ , flags(0)
+ , italicStyle(0.0f)
+ , scaleX(0)
+ , glyphs(nullptr)
+ , positions(nullptr) {}
// len is the number of bytes in text
ShadowText(const SkPaint* paint, float radius, uint32_t glyphCount, const glyph_t* srcGlyphs,
- const float* positions)
+ const float* positions)
: glyphCount(glyphCount)
, radius(radius)
, textSize(paint->getTextSize())
@@ -49,23 +56,17 @@ struct ShadowText {
, italicStyle(paint->getTextSkewX())
, scaleX(paint->getTextScaleX())
, glyphs(srcGlyphs)
- , positions(positions) {
- }
+ , positions(positions) {}
- ~ShadowText() {
- }
+ ~ShadowText() {}
hash_t hash() const;
static int compare(const ShadowText& lhs, const ShadowText& rhs);
- bool operator==(const ShadowText& other) const {
- return compare(*this, other) == 0;
- }
+ bool operator==(const ShadowText& other) const { return compare(*this, other) == 0; }
- bool operator!=(const ShadowText& other) const {
- return compare(*this, other) != 0;
- }
+ bool operator!=(const ShadowText& other) const { return compare(*this, other) != 0; }
void copyTextLocally() {
str.setTo(reinterpret_cast<const char16_t*>(glyphs), glyphCount);
@@ -91,7 +92,7 @@ struct ShadowText {
String16 str;
Vector<float> positionsCopy;
-}; // struct ShadowText
+}; // struct ShadowText
// Caching support
@@ -110,15 +111,14 @@ inline hash_t hash_type(const ShadowText& entry) {
/**
* Alpha texture used to represent a shadow.
*/
-struct ShadowTexture: public Texture {
- explicit ShadowTexture(Caches& caches): Texture(caches) {
- }
+struct ShadowTexture : public Texture {
+ explicit ShadowTexture(Caches& caches) : Texture(caches) {}
float left;
float top;
-}; // struct ShadowTexture
+}; // struct ShadowTexture
-class TextDropShadowCache: public OnEntryRemoved<ShadowText, ShadowTexture*> {
+class TextDropShadowCache : public OnEntryRemoved<ShadowText, ShadowTexture*> {
public:
TextDropShadowCache();
explicit TextDropShadowCache(uint32_t maxByteSize);
@@ -130,17 +130,15 @@ public:
*/
void operator()(ShadowText& text, ShadowTexture*& texture) override;
- ShadowTexture* get(const SkPaint* paint, const glyph_t* text,
- int numGlyphs, float radius, const float* positions);
+ ShadowTexture* get(const SkPaint* paint, const glyph_t* text, int numGlyphs, float radius,
+ const float* positions);
/**
* Clears the cache. This causes all textures to be deleted.
*/
void clear();
- void setFontRenderer(FontRenderer& fontRenderer) {
- mRenderer = &fontRenderer;
- }
+ void setFontRenderer(FontRenderer& fontRenderer) { mRenderer = &fontRenderer; }
/**
* Returns the maximum size of the cache in bytes.
@@ -158,9 +156,9 @@ private:
const uint32_t mMaxSize;
FontRenderer* mRenderer = nullptr;
bool mDebugEnabled;
-}; // class TextDropShadowCache
+}; // class TextDropShadowCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
+#endif // ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index b7c1e290370f..1e90eebe3bb8 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "Caches.h"
#include "Texture.h"
+#include "Caches.h"
#include "utils/GLUtils.h"
#include "utils/MathUtils.h"
#include "utils/TraceUtils.h"
@@ -32,22 +32,22 @@ namespace uirenderer {
// Number of bytes used by a texture in the given format
static int bytesPerPixel(GLint glFormat) {
switch (glFormat) {
- // The wrapped-texture case, usually means a SurfaceTexture
- case 0:
- return 0;
- case GL_LUMINANCE:
- case GL_ALPHA:
- return 1;
- case GL_SRGB8:
- case GL_RGB:
- return 3;
- case GL_SRGB8_ALPHA8:
- case GL_RGBA:
- return 4;
- case GL_RGBA16F:
- return 8;
- default:
- LOG_ALWAYS_FATAL("UNKNOWN FORMAT 0x%x", glFormat);
+ // The wrapped-texture case, usually means a SurfaceTexture
+ case 0:
+ return 0;
+ case GL_LUMINANCE:
+ case GL_ALPHA:
+ return 1;
+ case GL_SRGB8:
+ case GL_RGB:
+ return 3;
+ case GL_SRGB8_ALPHA8:
+ case GL_RGBA:
+ return 4;
+ case GL_RGBA16F:
+ return 8;
+ default:
+ LOG_ALWAYS_FATAL("UNKNOWN FORMAT 0x%x", glFormat);
}
}
@@ -92,13 +92,10 @@ void Texture::deleteTexture() {
}
}
-bool Texture::updateLayout(uint32_t width, uint32_t height, GLint internalFormat,
- GLint format, GLenum target) {
- if (mWidth == width
- && mHeight == height
- && mFormat == format
- && mInternalFormat == internalFormat
- && mTarget == target) {
+bool Texture::updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format,
+ GLenum target) {
+ if (mWidth == width && mHeight == height && mFormat == format &&
+ mInternalFormat == internalFormat && mTarget == target) {
return false;
}
mWidth = width;
@@ -117,8 +114,8 @@ void Texture::resetCachedParams() {
mMagFilter = GL_LINEAR;
}
-void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height,
- GLenum format, GLenum type, const void* pixels) {
+void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format,
+ GLenum type, const void* pixels) {
GL_CHECKPOINT(MODERATE);
// We don't have color space information, we assume the data is gamma encoded
@@ -132,11 +129,9 @@ void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height,
}
mCaches.textureState().bindTexture(GL_TEXTURE_2D, mId);
if (needsAlloc) {
- glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0,
- format, type, pixels);
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, pixels);
} else if (pixels) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0,
- format, type, pixels);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, pixels);
}
GL_CHECKPOINT(MODERATE);
}
@@ -148,15 +143,15 @@ void Texture::uploadHardwareBitmapToTexture(GraphicBuffer* buffer) {
mEglImageHandle = EGL_NO_IMAGE_KHR;
}
mEglImageHandle = eglCreateImageKHR(eglDisplayHandle, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- buffer->getNativeBuffer(), 0);
+ buffer->getNativeBuffer(), 0);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, mEglImageHandle);
}
static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GLenum type,
- GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height, const GLvoid * data) {
-
- const bool useStride = stride != width
- && Caches::getInstance().extensions().hasUnpackRowLength();
+ GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height,
+ const GLvoid* data) {
+ const bool useStride =
+ stride != width && Caches::getInstance().extensions().hasUnpackRowLength();
if ((stride == width) || useStride) {
if (useStride) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
@@ -175,11 +170,11 @@ static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GL
// With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
// if the stride doesn't match the width
- GLvoid * temp = (GLvoid *) malloc(width * height * bpp);
+ GLvoid* temp = (GLvoid*)malloc(width * height * bpp);
if (!temp) return;
- uint8_t * pDst = (uint8_t *)temp;
- uint8_t * pSrc = (uint8_t *)data;
+ uint8_t* pDst = (uint8_t*)temp;
+ uint8_t* pSrc = (uint8_t*)data;
for (GLsizei i = 0; i < height; i++) {
memcpy(pDst, pSrc, width * bpp);
pDst += width * bpp;
@@ -196,69 +191,70 @@ static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GL
}
}
-void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
- bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType) {
+void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType, bool needSRGB,
+ GLint* outInternalFormat, GLint* outFormat,
+ GLint* outType) {
switch (colorType) {
- case kAlpha_8_SkColorType:
- *outFormat = GL_ALPHA;
- *outInternalFormat = GL_ALPHA;
- *outType = GL_UNSIGNED_BYTE;
- break;
- case kRGB_565_SkColorType:
- if (needSRGB) {
- // We would ideally use a GL_RGB/GL_SRGB8 texture but the
- // intermediate Skia bitmap needs to be ARGB_8888
- *outFormat = GL_RGBA;
- *outInternalFormat = caches.rgbaInternalFormat();
+ case kAlpha_8_SkColorType:
+ *outFormat = GL_ALPHA;
+ *outInternalFormat = GL_ALPHA;
*outType = GL_UNSIGNED_BYTE;
- } else {
- *outFormat = GL_RGB;
- *outInternalFormat = GL_RGB;
- *outType = GL_UNSIGNED_SHORT_5_6_5;
- }
- break;
- // ARGB_4444 is upconverted to RGBA_8888
- case kARGB_4444_SkColorType:
- case kN32_SkColorType:
- *outFormat = GL_RGBA;
- *outInternalFormat = caches.rgbaInternalFormat(needSRGB);
- *outType = GL_UNSIGNED_BYTE;
- break;
- case kGray_8_SkColorType:
- *outFormat = GL_LUMINANCE;
- *outInternalFormat = GL_LUMINANCE;
- *outType = GL_UNSIGNED_BYTE;
- break;
- case kRGBA_F16_SkColorType:
- if (caches.extensions().getMajorGlVersion() >= 3) {
- // This format is always linear
- *outFormat = GL_RGBA;
- *outInternalFormat = GL_RGBA16F;
- *outType = GL_HALF_FLOAT;
- } else {
+ break;
+ case kRGB_565_SkColorType:
+ if (needSRGB) {
+ // We would ideally use a GL_RGB/GL_SRGB8 texture but the
+ // intermediate Skia bitmap needs to be ARGB_8888
+ *outFormat = GL_RGBA;
+ *outInternalFormat = caches.rgbaInternalFormat();
+ *outType = GL_UNSIGNED_BYTE;
+ } else {
+ *outFormat = GL_RGB;
+ *outInternalFormat = GL_RGB;
+ *outType = GL_UNSIGNED_SHORT_5_6_5;
+ }
+ break;
+ // ARGB_4444 is upconverted to RGBA_8888
+ case kARGB_4444_SkColorType:
+ case kN32_SkColorType:
*outFormat = GL_RGBA;
- *outInternalFormat = caches.rgbaInternalFormat(true);
+ *outInternalFormat = caches.rgbaInternalFormat(needSRGB);
*outType = GL_UNSIGNED_BYTE;
- }
- break;
- default:
- LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
- break;
+ break;
+ case kGray_8_SkColorType:
+ *outFormat = GL_LUMINANCE;
+ *outInternalFormat = GL_LUMINANCE;
+ *outType = GL_UNSIGNED_BYTE;
+ break;
+ case kRGBA_F16_SkColorType:
+ if (caches.extensions().getMajorGlVersion() >= 3) {
+ // This format is always linear
+ *outFormat = GL_RGBA;
+ *outInternalFormat = GL_RGBA16F;
+ *outType = GL_HALF_FLOAT;
+ } else {
+ *outFormat = GL_RGBA;
+ *outInternalFormat = caches.rgbaInternalFormat(true);
+ *outType = GL_UNSIGNED_BYTE;
+ }
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
+ break;
}
}
SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
- sk_sp<SkColorSpace> sRGB) {
+ sk_sp<SkColorSpace> sRGB) {
SkBitmap rgbaBitmap;
rgbaBitmap.allocPixels(SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
- bitmap.info().alphaType(), hasLinearBlending ? sRGB : nullptr));
+ bitmap.info().alphaType(),
+ hasLinearBlending ? sRGB : nullptr));
rgbaBitmap.eraseColor(0);
if (bitmap.colorType() == kRGBA_F16_SkColorType) {
// Drawing RGBA_F16 onto ARGB_8888 is not supported
- bitmap.readPixels(rgbaBitmap.info()
- .makeColorSpace(SkColorSpace::MakeSRGB()),
- rgbaBitmap.getPixels(), rgbaBitmap.rowBytes(), 0, 0);
+ bitmap.readPixels(rgbaBitmap.info().makeColorSpace(SkColorSpace::MakeSRGB()),
+ rgbaBitmap.getPixels(), rgbaBitmap.rowBytes(), 0, 0);
} else {
SkCanvas canvas(rgbaBitmap);
canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
@@ -268,12 +264,11 @@ SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
}
bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending) {
- return info.colorType() == kARGB_4444_SkColorType
- || (info.colorType() == kRGB_565_SkColorType
- && hasLinearBlending
- && info.colorSpace()->isSRGB())
- || (info.colorType() == kRGBA_F16_SkColorType
- && Caches::getInstance().extensions().getMajorGlVersion() < 3);
+ return info.colorType() == kARGB_4444_SkColorType ||
+ (info.colorType() == kRGB_565_SkColorType && hasLinearBlending &&
+ info.colorSpace()->isSRGB()) ||
+ (info.colorType() == kRGBA_F16_SkColorType &&
+ Caches::getInstance().extensions().getMajorGlVersion() < 3);
}
void Texture::upload(Bitmap& bitmap) {
@@ -298,13 +293,13 @@ void Texture::upload(Bitmap& bitmap) {
bool needSRGB = transferFunctionCloseToSRGB(bitmap.info().colorSpace());
GLint internalFormat, format, type;
- colorTypeToGlFormatAndType(mCaches, bitmap.colorType(),
- needSRGB && hasLinearBlending, &internalFormat, &format, &type);
+ colorTypeToGlFormatAndType(mCaches, bitmap.colorType(), needSRGB && hasLinearBlending,
+ &internalFormat, &format, &type);
// Some devices don't support GL_RGBA16F, so we need to compare the color type
// and internal GL format to decide what to do with 16 bit bitmaps
- bool rgba16fNeedsConversion = bitmap.colorType() == kRGBA_F16_SkColorType
- && internalFormat != GL_RGBA16F;
+ bool rgba16fNeedsConversion =
+ bitmap.colorType() == kRGBA_F16_SkColorType && internalFormat != GL_RGBA16F;
// RGBA16F is always linear extended sRGB
if (internalFormat == GL_RGBA16F) {
@@ -330,16 +325,16 @@ void Texture::upload(Bitmap& bitmap) {
float data[16];
xyzMatrix.asColMajorf(data);
- ColorSpace::TransferParameters p =
- {fn.fG, fn.fA, fn.fB, fn.fC, fn.fD, fn.fE, fn.fF};
- ColorSpace src("Unnamed", mat4f((const float*) &data[0]).upperLeft(), p);
+ ColorSpace::TransferParameters p = {fn.fG, fn.fA, fn.fB, fn.fC,
+ fn.fD, fn.fE, fn.fF};
+ ColorSpace src("Unnamed", mat4f((const float*)&data[0]).upperLeft(), p);
mConnector.reset(new ColorSpaceConnector(src, ColorSpace::sRGB()));
// A non-sRGB color space might have a transfer function close enough to sRGB
// that we can save shader instructions by using an sRGB sampler
// This is only possible if we have hardware support for sRGB textures
- if (needSRGB && internalFormat == GL_RGBA
- && mCaches.extensions().hasSRGB() && !bitmap.isHardware()) {
+ if (needSRGB && internalFormat == GL_RGBA && mCaches.extensions().hasSRGB() &&
+ !bitmap.isHardware()) {
internalFormat = GL_SRGB8_ALPHA8;
}
}
@@ -360,13 +355,14 @@ void Texture::upload(Bitmap& bitmap) {
sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
- rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(),
- rgbaBitmap.height(), rgbaBitmap.getPixels());
+ rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(), rgbaBitmap.height(),
+ rgbaBitmap.getPixels());
} else if (bitmap.isHardware()) {
uploadHardwareBitmapToTexture(bitmap.graphicBuffer());
} else {
uploadToTexture(needsAlloc, internalFormat, format, type, bitmap.rowBytesAsPixels(),
- bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(), bitmap.pixels());
+ bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(),
+ bitmap.pixels());
}
if (canMipMap) {
@@ -382,8 +378,8 @@ void Texture::upload(Bitmap& bitmap) {
}
}
-void Texture::wrap(GLuint id, uint32_t width, uint32_t height,
- GLint internalFormat, GLint format, GLenum target) {
+void Texture::wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format,
+ GLenum target) {
mId = id;
mWidth = width;
mHeight = height;
@@ -399,8 +395,8 @@ TransferFunctionType Texture::getTransferFunctionType() const {
if (mConnector.get() != nullptr && mInternalFormat != GL_SRGB8_ALPHA8) {
const ColorSpace::TransferParameters& p = mConnector->getSource().getTransferParameters();
if (MathUtils::isZero(p.e) && MathUtils::isZero(p.f)) {
- if (MathUtils::areEqual(p.a, 1.0f) && MathUtils::isZero(p.b)
- && MathUtils::isZero(p.c) && MathUtils::isZero(p.d)) {
+ if (MathUtils::areEqual(p.a, 1.0f) && MathUtils::isZero(p.b) &&
+ MathUtils::isZero(p.c) && MathUtils::isZero(p.d)) {
if (MathUtils::areEqual(p.g, 1.0f)) {
return TransferFunctionType::None;
}
@@ -413,5 +409,5 @@ TransferFunctionType Texture::getTransferFunctionType() const {
return TransferFunctionType::None;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 7f742e604838..5b7e4e261f30 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -27,10 +27,10 @@
#include <ui/ColorSpace.h>
-#include <GLES2/gl2.h>
-#include <GLES3/gl3.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
#include <SkBitmap.h>
namespace android {
@@ -48,32 +48,30 @@ class Layer;
*/
class Texture : public GpuMemoryTracker {
public:
- static SkBitmap uploadToN32(const SkBitmap& bitmap,
- bool hasLinearBlending, sk_sp<SkColorSpace> sRGB);
+ static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
+ sk_sp<SkColorSpace> sRGB);
static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending);
static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
- bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType);
+ bool needSRGB, GLint* outInternalFormat,
+ GLint* outFormat, GLint* outType);
- explicit Texture(Caches& caches)
- : GpuMemoryTracker(GpuObjectType::Texture)
- , mCaches(caches)
- { }
+ explicit Texture(Caches& caches) : GpuMemoryTracker(GpuObjectType::Texture), mCaches(caches) {}
- virtual ~Texture() { }
+ virtual ~Texture() {}
inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
setWrapST(wrap, wrap, bindTexture, force);
}
virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
- bool force = false);
+ bool force = false);
inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
setFilterMinMag(filter, filter, bindTexture, force);
}
virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
- bool force = false);
+ bool force = false);
/**
* Convenience method to call glDeleteTextures() on this texture's id.
@@ -89,7 +87,7 @@ public:
*/
void resize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
upload(internalFormat, width, height, format,
- internalFormat == GL_RGBA16F ? GL_HALF_FLOAT : GL_UNSIGNED_BYTE, nullptr);
+ internalFormat == GL_RGBA16F ? GL_HALF_FLOAT : GL_UNSIGNED_BYTE, nullptr);
}
/**
@@ -104,60 +102,42 @@ public:
/**
* Basically glTexImage2D/glTexSubImage2D.
*/
- void upload(GLint internalFormat, uint32_t width, uint32_t height,
- GLenum format, GLenum type, const void* pixels);
+ void upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format, GLenum type,
+ const void* pixels);
/**
* Wraps an existing texture.
*/
- void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat,
- GLint format, GLenum target);
+ void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format,
+ GLenum target);
- GLuint id() const {
- return mId;
- }
+ GLuint id() const { return mId; }
- uint32_t width() const {
- return mWidth;
- }
+ uint32_t width() const { return mWidth; }
- uint32_t height() const {
- return mHeight;
- }
+ uint32_t height() const { return mHeight; }
- GLint format() const {
- return mFormat;
- }
+ GLint format() const { return mFormat; }
- GLint internalFormat() const {
- return mInternalFormat;
- }
+ GLint internalFormat() const { return mInternalFormat; }
- GLenum target() const {
- return mTarget;
- }
+ GLenum target() const { return mTarget; }
/**
* Returns nullptr if this texture does not require color space conversion
* to sRGB, or a valid pointer to a ColorSpaceConnector if a conversion
* is required.
*/
- constexpr const ColorSpaceConnector* getColorSpaceConnector() const {
- return mConnector.get();
- }
+ constexpr const ColorSpaceConnector* getColorSpaceConnector() const { return mConnector.get(); }
- constexpr bool hasColorSpaceConversion() const {
- return mConnector.get() != nullptr;
- }
+ constexpr bool hasColorSpaceConversion() const { return mConnector.get() != nullptr; }
TransferFunctionType getTransferFunctionType() const;
/**
* Returns true if this texture uses a linear encoding format.
*/
- constexpr bool isLinear() const {
- return mIsLinear;
- }
+ constexpr bool isLinear() const { return mIsLinear; }
/**
* Generation of the backing bitmap,
@@ -190,6 +170,7 @@ public:
* the current frame. This is reset at the start of a new frame.
*/
void* isInUse = nullptr;
+
private:
// TODO: Temporarily grant private access to GlLayer, remove once
// GlLayer can be de-tangled from being a dual-purpose render target
@@ -197,8 +178,8 @@ private:
friend class GlLayer;
// Returns true if the texture layout (size, format, etc.) changed, false if it was the same
- bool updateLayout(uint32_t width, uint32_t height, GLint internalFormat,
- GLint format, GLenum target);
+ bool updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format,
+ GLenum target);
void uploadHardwareBitmapToTexture(GraphicBuffer* buffer);
void resetCachedParams();
@@ -226,12 +207,11 @@ private:
Caches& mCaches;
std::unique_ptr<ColorSpaceConnector> mConnector;
-}; // struct Texture
+}; // struct Texture
class AutoTexture {
public:
- explicit AutoTexture(Texture* texture)
- : texture(texture) {}
+ explicit AutoTexture(Texture* texture) : texture(texture) {}
~AutoTexture() {
if (texture && texture->cleanup) {
texture->deleteTexture();
@@ -240,9 +220,9 @@ public:
}
Texture* const texture;
-}; // class AutoTexture
+}; // class AutoTexture
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_TEXTURE_H
+#endif // ANDROID_HWUI_TEXTURE_H
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 6fe3606a7576..9d365fb29ebe 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -19,12 +19,12 @@
#include <utils/Mutex.h>
#include "Caches.h"
+#include "DeviceInfo.h"
+#include "Properties.h"
#include "Texture.h"
#include "TextureCache.h"
-#include "Properties.h"
-#include "utils/TraceUtils.h"
#include "hwui/Bitmap.h"
-#include "DeviceInfo.h"
+#include "utils/TraceUtils.h"
namespace android {
namespace uirenderer {
@@ -36,7 +36,7 @@ namespace uirenderer {
TextureCache::TextureCache()
: mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity)
, mSize(0)
- , mMaxSize(DeviceInfo::multiplyByResolution(4 * 6)) // 6 screen-sized RGBA_8888 bitmaps
+ , mMaxSize(DeviceInfo::multiplyByResolution(4 * 6)) // 6 screen-sized RGBA_8888 bitmaps
, mFlushRate(.4f) {
mCache.setOnEntryRemovedListener(this);
mMaxTextureSize = DeviceInfo::get()->maxTextureSize();
@@ -67,8 +67,8 @@ void TextureCache::operator()(uint32_t&, Texture*& texture) {
// This will be called already locked
if (texture) {
mSize -= texture->bitmapSize;
- TEXTURE_LOGD("TextureCache::callback: name, removed size, mSize = %d, %d, %d",
- texture->id, texture->bitmapSize, mSize);
+ TEXTURE_LOGD("TextureCache::callback: name, removed size, mSize = %d, %d, %d", texture->id,
+ texture->bitmapSize, mSize);
if (mDebugEnabled) {
ALOGD("Texture deleted, size = %d", texture->bitmapSize);
}
@@ -92,19 +92,19 @@ void TextureCache::resetMarkInUse(void* ownerToken) {
bool TextureCache::canMakeTextureFromBitmap(Bitmap* bitmap) {
if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
- ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
- bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
+ ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)", bitmap->width(),
+ bitmap->height(), mMaxTextureSize, mMaxTextureSize);
return false;
}
return true;
}
Texture* TextureCache::createTexture(Bitmap* bitmap) {
- Texture* texture = new Texture(Caches::getInstance());
- texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
- texture->generation = bitmap->getGenerationID();
- texture->upload(*bitmap);
- return texture;
+ Texture* texture = new Texture(Caches::getInstance());
+ texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
+ texture->generation = bitmap->getGenerationID();
+ texture->upload(*bitmap);
+ return texture;
}
// Returns a prepared Texture* that either is already in the cache or can fit
@@ -113,9 +113,9 @@ Texture* TextureCache::getCachedTexture(Bitmap* bitmap) {
if (bitmap->isHardware()) {
auto textureIterator = mHardwareTextures.find(bitmap->getStableID());
if (textureIterator == mHardwareTextures.end()) {
- Texture* texture = createTexture(bitmap);
- mHardwareTextures.insert(std::make_pair(bitmap->getStableID(),
- std::unique_ptr<Texture>(texture)));
+ Texture* texture = createTexture(bitmap);
+ mHardwareTextures.insert(
+ std::make_pair(bitmap->getStableID(), std::unique_ptr<Texture>(texture)));
if (mDebugEnabled) {
ALOGD("Texture created for hw bitmap size = %d", texture->bitmapSize);
}
@@ -147,7 +147,7 @@ Texture* TextureCache::getCachedTexture(Bitmap* bitmap) {
texture = createTexture(bitmap);
mSize += size;
TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
- bitmap, texture->id, size, mSize);
+ bitmap, texture->id, size, mSize);
if (mDebugEnabled) {
ALOGD("Texture created, size = %d", size);
}
@@ -201,7 +201,7 @@ bool TextureCache::destroyTexture(uint32_t pixelRefStableID) {
void TextureCache::clear() {
mCache.clear();
- for(auto& iter: mHardwareTextures) {
+ for (auto& iter : mHardwareTextures) {
iter.second->deleteTexture();
}
mHardwareTextures.clear();
@@ -223,5 +223,5 @@ void TextureCache::flush() {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 776ff8a03fd1..19e7bea99669 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -26,8 +26,8 @@
#include "Debug.h"
-#include <vector>
#include <unordered_map>
+#include <vector>
namespace android {
@@ -43,9 +43,9 @@ class Texture;
// Debug
#if DEBUG_TEXTURES
- #define TEXTURE_LOGD(...) ALOGD(__VA_ARGS__)
+#define TEXTURE_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define TEXTURE_LOGD(...)
+#define TEXTURE_LOGD(...)
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -136,9 +136,9 @@ private:
bool mDebugEnabled;
std::unordered_map<uint32_t, std::unique_ptr<Texture>> mHardwareTextures;
-}; // class TextureCache
+}; // class TextureCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_TEXTURE_CACHE_H
+#endif // ANDROID_HWUI_TEXTURE_CACHE_H
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index e39614b6a5ea..b37f2cfe7fee 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -37,6 +37,7 @@ class RenderState;
class ErrorHandler {
public:
virtual void onError(const std::string& message) = 0;
+
protected:
~ErrorHandler() {}
};
@@ -48,6 +49,7 @@ public:
// is finished it is possible that the node was "resurrected" and has
// a non-zero parent count.
virtual void onMaybeRemovedFromTree(RenderNode* node) = 0;
+
protected:
virtual ~TreeObserver() {}
};
@@ -55,6 +57,7 @@ protected:
// This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN
class TreeInfo {
PREVENT_COPY_AND_ASSIGN(TreeInfo);
+
public:
enum TraversalMode {
// The full monty - sync, push, run animators, etc... Used by DrawFrameTask
@@ -68,10 +71,7 @@ public:
};
TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContext)
- : mode(mode)
- , prepareTextures(mode == MODE_FULL)
- , canvasContext(canvasContext)
- {}
+ : mode(mode), prepareTextures(mode == MODE_FULL), canvasContext(canvasContext) {}
TraversalMode mode;
// TODO: Remove this? Currently this is used to signal to stop preparing
@@ -108,6 +108,12 @@ public:
// *OR* will post itself for the next vsync automatically, use this
// only to avoid calling draw()
bool canDrawThisFrame = true;
+ // Sentinel for animatedImageDelay meaning there is no need to post such
+ // a message.
+ static constexpr nsecs_t kNoAnimatedImageDelay = -1;
+ // This is used to post a message to redraw when it is time to draw the
+ // next frame of an AnimatedImageDrawable.
+ nsecs_t animatedImageDelay = kNoAnimatedImageDelay;
} out;
// This flag helps to disable projection for receiver nodes that do not have any backward
diff --git a/libs/hwui/UvMapper.h b/libs/hwui/UvMapper.h
index 70428d2efd51..b495e3394bc9 100644
--- a/libs/hwui/UvMapper.h
+++ b/libs/hwui/UvMapper.h
@@ -33,15 +33,14 @@ public:
* Using this constructor is equivalent to not using any mapping at all.
* UV coordinates in the [0..1] range remain in the [0..1] range.
*/
- UvMapper(): mIdentity(true), mMinU(0.0f), mMaxU(1.0f), mMinV(0.0f), mMaxV(1.0f) {
- }
+ UvMapper() : mIdentity(true), mMinU(0.0f), mMaxU(1.0f), mMinV(0.0f), mMaxV(1.0f) {}
/**
* Creates a new mapper with the specified ranges for U and V coordinates.
* The parameter minU must be < maxU and minV must be < maxV.
*/
- UvMapper(float minU, float maxU, float minV, float maxV):
- mMinU(minU), mMaxU(maxU), mMinV(minV), mMaxV(maxV) {
+ UvMapper(float minU, float maxU, float minV, float maxV)
+ : mMinU(minU), mMaxU(maxU), mMinV(minV), mMaxV(maxV) {
checkIdentity();
}
@@ -49,9 +48,7 @@ public:
* Returns true if calling the map*() methods has no effect (that is,
* texture coordinates remain in the 0..1 range.)
*/
- bool isIdentity() const {
- return mIdentity;
- }
+ bool isIdentity() const { return mIdentity; }
/**
* Changes the U and V mapping ranges.
@@ -127,7 +124,7 @@ private:
float mMaxV;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_UV_MAPPER_H
+#endif // ANDROID_HWUI_UV_MAPPER_H
diff --git a/libs/hwui/Vector.h b/libs/hwui/Vector.h
index 6367dbd7b660..d2c15ad872a5 100644
--- a/libs/hwui/Vector.h
+++ b/libs/hwui/Vector.h
@@ -32,13 +32,9 @@ struct Vector2 {
float x;
float y;
- float lengthSquared() const {
- return x * x + y * y;
- }
+ float lengthSquared() const { return x * x + y * y; }
- float length() const {
- return sqrt(x * x + y * y);
- }
+ float length() const { return sqrt(x * x + y * y); }
void operator+=(const Vector2& v) {
x += v.x;
@@ -70,21 +66,13 @@ struct Vector2 {
y *= s;
}
- Vector2 operator+(const Vector2& v) const {
- return (Vector2){x + v.x, y + v.y};
- }
+ Vector2 operator+(const Vector2& v) const { return (Vector2){x + v.x, y + v.y}; }
- Vector2 operator-(const Vector2& v) const {
- return (Vector2){x - v.x, y - v.y};
- }
+ Vector2 operator-(const Vector2& v) const { return (Vector2){x - v.x, y - v.y}; }
- Vector2 operator/(float s) const {
- return (Vector2){x / s, y / s};
- }
+ Vector2 operator/(float s) const { return (Vector2){x / s, y / s}; }
- Vector2 operator*(float s) const {
- return (Vector2){x * s, y * s};
- }
+ Vector2 operator*(float s) const { return (Vector2){x * s, y * s}; }
void normalize() {
float s = 1.0f / length();
@@ -98,18 +86,12 @@ struct Vector2 {
return v;
}
- float dot(const Vector2& v) const {
- return x * v.x + y * v.y;
- }
+ float dot(const Vector2& v) const { return x * v.x + y * v.y; }
- float cross(const Vector2& v) const {
- return x * v.y - y * v.x;
- }
+ float cross(const Vector2& v) const { return x * v.y - y * v.x; }
- void dump() {
- ALOGD("Vector2[%.2f, %.2f]", x, y);
- }
-}; // class Vector2
+ void dump() { ALOGD("Vector2[%.2f, %.2f]", x, y); }
+}; // class Vector2
// MUST BE A POD - this means no ctor or dtor!
class Vector3 {
@@ -118,29 +100,20 @@ public:
float y;
float z;
- Vector3 operator+(const Vector3& v) const {
- return (Vector3){x + v.x, y + v.y, z + v.z};
- }
+ Vector3 operator+(const Vector3& v) const { return (Vector3){x + v.x, y + v.y, z + v.z}; }
- Vector3 operator-(const Vector3& v) const {
- return (Vector3){x - v.x, y - v.y, z - v.z};
- }
+ Vector3 operator-(const Vector3& v) const { return (Vector3){x - v.x, y - v.y, z - v.z}; }
- Vector3 operator/(float s) const {
- return (Vector3){x / s, y / s, z / s};
- }
-
- Vector3 operator*(float s) const {
- return (Vector3){x * s, y * s, z * s};
- }
+ Vector3 operator/(float s) const { return (Vector3){x / s, y / s, z / s}; }
+ Vector3 operator*(float s) const { return (Vector3){x * s, y * s, z * s}; }
void dump(const char* label = "Vector3") const {
ALOGD("%s[%.2f, %.2f, %.2f]", label, x, y, z);
}
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_VECTOR_H
+#endif // ANDROID_HWUI_VECTOR_H
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index ca179c9a25d2..18358e25fd5b 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -16,11 +16,11 @@
#include "VectorDrawable.h"
+#include <utils/Log.h>
#include "PathParser.h"
#include "SkColorFilter.h"
#include "SkImageInfo.h"
#include "SkShader.h"
-#include <utils/Log.h>
#include "utils/Macros.h"
#include "utils/TraceUtils.h"
#include "utils/VectorDrawableUtils.h"
@@ -79,7 +79,7 @@ FullPath::FullPath(const FullPath& path) : Path(path) {
}
static void applyTrim(SkPath* outPath, const SkPath& inPath, float trimPathStart, float trimPathEnd,
- float trimPathOffset) {
+ float trimPathOffset) {
if (trimPathStart == 0.0f && trimPathEnd == 1.0f) {
*outPath = inPath;
return;
@@ -109,25 +109,25 @@ const SkPath& FullPath::getUpdatedPath(bool useStagingData, SkPath* tempStagingP
return mTrimmedSkPath;
}
Path::getUpdatedPath(useStagingData, tempStagingPath);
- SkPath *outPath;
+ SkPath* outPath;
if (useStagingData) {
SkPath inPath = *tempStagingPath;
applyTrim(tempStagingPath, inPath, mStagingProperties.getTrimPathStart(),
- mStagingProperties.getTrimPathEnd(), mStagingProperties.getTrimPathOffset());
+ mStagingProperties.getTrimPathEnd(), mStagingProperties.getTrimPathOffset());
outPath = tempStagingPath;
} else {
if (mProperties.getTrimPathStart() != 0.0f || mProperties.getTrimPathEnd() != 1.0f) {
mProperties.mTrimDirty = false;
applyTrim(&mTrimmedSkPath, mSkPath, mProperties.getTrimPathStart(),
- mProperties.getTrimPathEnd(), mProperties.getTrimPathOffset());
+ mProperties.getTrimPathEnd(), mProperties.getTrimPathOffset());
outPath = &mTrimmedSkPath;
} else {
outPath = &mSkPath;
}
}
const FullPathProperties& properties = useStagingData ? mStagingProperties : mProperties;
- bool setFillPath = properties.getFillGradient() != nullptr
- || properties.getFillColor() != SK_ColorTRANSPARENT;
+ bool setFillPath = properties.getFillGradient() != nullptr ||
+ properties.getFillColor() != SK_ColorTRANSPARENT;
if (setFillPath) {
SkPath::FillType ft = static_cast<SkPath::FillType>(properties.getFillType());
outPath->setFillType(ft);
@@ -138,11 +138,10 @@ const SkPath& FullPath::getUpdatedPath(bool useStagingData, SkPath* tempStagingP
void FullPath::dump() {
Path::dump();
ALOGD("stroke width, color, alpha: %f, %d, %f, fill color, alpha: %d, %f",
- mProperties.getStrokeWidth(), mProperties.getStrokeColor(), mProperties.getStrokeAlpha(),
- mProperties.getFillColor(), mProperties.getFillAlpha());
+ mProperties.getStrokeWidth(), mProperties.getStrokeColor(), mProperties.getStrokeAlpha(),
+ mProperties.getFillColor(), mProperties.getFillAlpha());
}
-
inline SkColor applyAlpha(SkColor color, float alpha) {
int alphaBytes = SkColorGetA(color);
return SkColorSetA(color, alphaBytes * alpha);
@@ -167,7 +166,7 @@ void FullPath::draw(SkCanvas* outCanvas, bool useStagingData) {
if (needsFill) {
paint.setStyle(SkPaint::Style::kFill_Style);
- paint.setAntiAlias(true);
+ paint.setAntiAlias(mAntiAlias);
outCanvas->drawPath(renderPath, paint);
}
@@ -183,7 +182,7 @@ void FullPath::draw(SkCanvas* outCanvas, bool useStagingData) {
}
if (needsStroke) {
paint.setStyle(SkPaint::Style::kStroke_Style);
- paint.setAntiAlias(true);
+ paint.setAntiAlias(mAntiAlias);
paint.setStrokeJoin(SkPaint::Join(properties.getStrokeLineJoin()));
paint.setStrokeCap(SkPaint::Cap(properties.getStrokeLineCap()));
paint.setStrokeMiter(properties.getStrokeMiterLimit());
@@ -213,7 +212,7 @@ bool FullPath::FullPathProperties::copyProperties(int8_t* outProperties, int len
int propertyDataSize = sizeof(FullPathProperties::PrimitiveFields);
if (length != propertyDataSize) {
LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
- propertyDataSize, length);
+ propertyDataSize, length);
return false;
}
@@ -229,35 +228,37 @@ void FullPath::FullPathProperties::setColorPropertyValue(int propertyId, int32_t
} else if (currentProperty == Property::fillColor) {
setFillColor(value);
} else {
- LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property"
- " with id: %d", propertyId);
+ LOG_ALWAYS_FATAL(
+ "Error setting color property on FullPath: No valid property"
+ " with id: %d",
+ propertyId);
}
}
void FullPath::FullPathProperties::setPropertyValue(int propertyId, float value) {
Property property = static_cast<Property>(propertyId);
switch (property) {
- case Property::strokeWidth:
- setStrokeWidth(value);
- break;
- case Property::strokeAlpha:
- setStrokeAlpha(value);
- break;
- case Property::fillAlpha:
- setFillAlpha(value);
- break;
- case Property::trimPathStart:
- setTrimPathStart(value);
- break;
- case Property::trimPathEnd:
- setTrimPathEnd(value);
- break;
- case Property::trimPathOffset:
- setTrimPathOffset(value);
- break;
- default:
- LOG_ALWAYS_FATAL("Invalid property id: %d for animation", propertyId);
- break;
+ case Property::strokeWidth:
+ setStrokeWidth(value);
+ break;
+ case Property::strokeAlpha:
+ setStrokeAlpha(value);
+ break;
+ case Property::fillAlpha:
+ setFillAlpha(value);
+ break;
+ case Property::trimPathStart:
+ setTrimPathStart(value);
+ break;
+ case Property::trimPathEnd:
+ setTrimPathEnd(value);
+ break;
+ case Property::trimPathOffset:
+ setTrimPathOffset(value);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid property id: %d for animation", propertyId);
+ break;
}
}
@@ -288,7 +289,7 @@ void Group::draw(SkCanvas* outCanvas, bool useStagingData) {
void Group::dump() {
ALOGD("Group %s has %zu children: ", mName.c_str(), mChildren.size());
ALOGD("Group translateX, Y : %f, %f, scaleX, Y: %f, %f", mProperties.getTranslateX(),
- mProperties.getTranslateY(), mProperties.getScaleX(), mProperties.getScaleY());
+ mProperties.getTranslateY(), mProperties.getScaleX(), mProperties.getScaleY());
for (size_t i = 0; i < mChildren.size(); i++) {
mChildren[i]->dump();
}
@@ -315,7 +316,7 @@ void Group::getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& propertie
outMatrix->postScale(properties.getScaleX(), properties.getScaleY());
outMatrix->postRotate(properties.getRotation(), 0, 0);
outMatrix->postTranslate(properties.getTranslateX() + properties.getPivotX(),
- properties.getTranslateY() + properties.getPivotY());
+ properties.getTranslateY() + properties.getPivotY());
}
void Group::addChild(Node* child) {
@@ -329,7 +330,7 @@ bool Group::GroupProperties::copyProperties(float* outProperties, int length) co
int propertyCount = static_cast<int>(Property::count);
if (length != propertyCount) {
LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
- propertyCount, length);
+ propertyCount, length);
return false;
}
@@ -343,23 +344,23 @@ bool Group::GroupProperties::copyProperties(float* outProperties, int length) co
float Group::GroupProperties::getPropertyValue(int propertyId) const {
Property currentProperty = static_cast<Property>(propertyId);
switch (currentProperty) {
- case Property::rotate:
- return getRotation();
- case Property::pivotX:
- return getPivotX();
- case Property::pivotY:
- return getPivotY();
- case Property::scaleX:
- return getScaleX();
- case Property::scaleY:
- return getScaleY();
- case Property::translateX:
- return getTranslateX();
- case Property::translateY:
- return getTranslateY();
- default:
- LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
- return 0;
+ case Property::rotate:
+ return getRotation();
+ case Property::pivotX:
+ return getPivotX();
+ case Property::pivotY:
+ return getPivotY();
+ case Property::scaleX:
+ return getScaleX();
+ case Property::scaleY:
+ return getScaleY();
+ case Property::translateX:
+ return getTranslateX();
+ case Property::translateY:
+ return getTranslateY();
+ default:
+ LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
+ return 0;
}
}
@@ -367,29 +368,29 @@ float Group::GroupProperties::getPropertyValue(int propertyId) const {
void Group::GroupProperties::setPropertyValue(int propertyId, float value) {
Property currentProperty = static_cast<Property>(propertyId);
switch (currentProperty) {
- case Property::rotate:
- setRotation(value);
- break;
- case Property::pivotX:
- setPivotX(value);
- break;
- case Property::pivotY:
- setPivotY(value);
- break;
- case Property::scaleX:
- setScaleX(value);
- break;
- case Property::scaleY:
- setScaleY(value);
- break;
- case Property::translateX:
- setTranslateX(value);
- break;
- case Property::translateY:
- setTranslateY(value);
- break;
- default:
- LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
+ case Property::rotate:
+ setRotation(value);
+ break;
+ case Property::pivotX:
+ setPivotX(value);
+ break;
+ case Property::pivotY:
+ setPivotY(value);
+ break;
+ case Property::scaleX:
+ setScaleX(value);
+ break;
+ case Property::scaleY:
+ setScaleY(value);
+ break;
+ case Property::translateX:
+ setTranslateX(value);
+ break;
+ case Property::translateY:
+ setTranslateY(value);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
}
}
@@ -401,8 +402,8 @@ bool Group::GroupProperties::isValidProperty(int propertyId) {
return propertyId >= 0 && propertyId < static_cast<int>(Property::count);
}
-int Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
- const SkRect& bounds, bool needsMirroring, bool canReuseCache) {
+int Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, const SkRect& bounds,
+ bool needsMirroring, bool canReuseCache) {
// The imageView can scale the canvas in different ways, in order to
// avoid blurry scaling, we have to draw into a bitmap with exact pixel
// size first. This bitmap size is determined by the bounds and the
@@ -417,8 +418,8 @@ int Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
canvasScaleX = fabs(canvasMatrix.getScaleX());
canvasScaleY = fabs(canvasMatrix.getScaleY());
}
- int scaledWidth = (int) (bounds.width() * canvasScaleX);
- int scaledHeight = (int) (bounds.height() * canvasScaleY);
+ int scaledWidth = (int)(bounds.width() * canvasScaleX);
+ int scaledHeight = (int)(bounds.height() * canvasScaleY);
scaledWidth = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledWidth);
scaledHeight = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledHeight);
@@ -449,8 +450,8 @@ int Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
}
void Tree::drawStaging(Canvas* outCanvas) {
- bool redrawNeeded = allocateBitmapIfNeeded(mStagingCache,
- mStagingProperties.getScaledWidth(), mStagingProperties.getScaledHeight());
+ bool redrawNeeded = allocateBitmapIfNeeded(mStagingCache, mStagingProperties.getScaledWidth(),
+ mStagingProperties.getScaledHeight());
// draw bitmap cache
if (redrawNeeded || mStagingCache.dirty) {
updateBitmapCache(*mStagingCache.bitmap, true);
@@ -459,10 +460,11 @@ void Tree::drawStaging(Canvas* outCanvas) {
SkPaint tmpPaint;
SkPaint* paint = updatePaint(&tmpPaint, &mStagingProperties);
- outCanvas->drawBitmap(*mStagingCache.bitmap, 0, 0,
- mStagingCache.bitmap->width(), mStagingCache.bitmap->height(),
- mStagingProperties.getBounds().left(), mStagingProperties.getBounds().top(),
- mStagingProperties.getBounds().right(), mStagingProperties.getBounds().bottom(), paint);
+ outCanvas->drawBitmap(*mStagingCache.bitmap, 0, 0, mStagingCache.bitmap->width(),
+ mStagingCache.bitmap->height(), mStagingProperties.getBounds().left(),
+ mStagingProperties.getBounds().top(),
+ mStagingProperties.getBounds().right(),
+ mStagingProperties.getBounds().bottom(), paint);
}
SkPaint* Tree::getPaint() {
@@ -484,7 +486,7 @@ SkPaint* Tree::updatePaint(SkPaint* outPaint, TreeProperties* prop) {
Bitmap& Tree::getBitmapUpdateIfDirty() {
bool redrawNeeded = allocateBitmapIfNeeded(mCache, mProperties.getScaledWidth(),
- mProperties.getScaledHeight());
+ mProperties.getScaledHeight());
if (redrawNeeded || mCache.dirty) {
updateBitmapCache(*mCache.bitmap, false);
mCache.dirty = false;
@@ -495,8 +497,8 @@ Bitmap& Tree::getBitmapUpdateIfDirty() {
void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context) {
SkRect dst;
sk_sp<SkSurface> surface = mCache.getSurface(&dst);
- bool canReuseSurface = surface && dst.width() >= mProperties.getScaledWidth()
- && dst.height() >= mProperties.getScaledHeight();
+ bool canReuseSurface = surface && dst.width() >= mProperties.getScaledWidth() &&
+ dst.height() >= mProperties.getScaledHeight();
if (!canReuseSurface) {
int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
@@ -506,33 +508,24 @@ void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext*
surface = atlasEntry.surface;
mCache.setAtlas(atlas, atlasEntry.key);
} else {
- //don't draw, if we failed to allocate an offscreen buffer
+ // don't draw, if we failed to allocate an offscreen buffer
mCache.clear();
surface.reset();
}
}
if (!canReuseSurface || mCache.dirty) {
- draw(surface.get(), dst);
+ if (surface) {
+ Bitmap& bitmap = getBitmapUpdateIfDirty();
+ SkBitmap skiaBitmap;
+ bitmap.getSkBitmap(&skiaBitmap);
+ surface->writePixels(skiaBitmap, dst.fLeft, dst.fTop);
+ }
mCache.dirty = false;
}
}
-void Tree::draw(SkSurface* surface, const SkRect& dst) {
- if (surface) {
- SkCanvas* canvas = surface->getCanvas();
- float scaleX = dst.width() / mProperties.getViewportWidth();
- float scaleY = dst.height() / mProperties.getViewportHeight();
- SkAutoCanvasRestore acr(canvas, true);
- canvas->translate(dst.fLeft, dst.fTop);
- canvas->clipRect(SkRect::MakeWH(dst.width(), dst.height()));
- canvas->clear(SK_ColorTRANSPARENT);
- canvas->scale(scaleX, scaleY);
- mRootNode->draw(canvas, false);
- }
-}
-
void Tree::Cache::setAtlas(sp<skiapipeline::VectorDrawableAtlas> newAtlas,
- skiapipeline::AtlasKey newAtlasKey) {
+ skiapipeline::AtlasKey newAtlasKey) {
LOG_ALWAYS_FATAL_IF(newAtlasKey == INVALID_ATLAS_KEY);
clear();
mAtlas = newAtlas;
@@ -561,32 +554,25 @@ void Tree::Cache::clear() {
mAtlasKey = INVALID_ATLAS_KEY;
}
-void Tree::draw(SkCanvas* canvas) {
+void Tree::draw(SkCanvas* canvas, const SkRect& bounds) {
SkRect src;
sk_sp<SkSurface> vdSurface = mCache.getSurface(&src);
if (vdSurface) {
canvas->drawImageRect(vdSurface->makeImageSnapshot().get(), src,
- mutateProperties()->getBounds(), getPaint());
+ bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint);
} else {
// Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure.
// We render the VD into a temporary standalone buffer and mark the frame as dirty. Next
// frame will be cached into the atlas.
+ Bitmap& bitmap = getBitmapUpdateIfDirty();
+ SkBitmap skiaBitmap;
+ bitmap.getSkBitmap(&skiaBitmap);
+
int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
- SkRect src = SkRect::MakeWH(scaledWidth, scaledHeight);
-#ifndef ANDROID_ENABLE_LINEAR_BLENDING
- sk_sp<SkColorSpace> colorSpace = nullptr;
-#else
- sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
-#endif
- SkImageInfo info = SkImageInfo::MakeN32(scaledWidth, scaledHeight, kPremul_SkAlphaType,
- colorSpace);
- sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(canvas->getGrContext(),
- SkBudgeted::kYes, info);
- draw(surface.get(), src);
+ canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight),
+ bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint);
mCache.clear();
- canvas->drawImageRect(surface->makeImageSnapshot().get(), mutateProperties()->getBounds(),
- getPaint());
markDirty();
}
}
@@ -599,10 +585,10 @@ void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) {
ATRACE_FORMAT("VectorDrawable repaint %dx%d", cacheWidth, cacheHeight);
outCache.eraseColor(SK_ColorTRANSPARENT);
SkCanvas outCanvas(outCache);
- float viewportWidth = useStagingData ?
- mStagingProperties.getViewportWidth() : mProperties.getViewportWidth();
- float viewportHeight = useStagingData ?
- mStagingProperties.getViewportHeight() : mProperties.getViewportHeight();
+ float viewportWidth =
+ useStagingData ? mStagingProperties.getViewportWidth() : mProperties.getViewportWidth();
+ float viewportHeight = useStagingData ? mStagingProperties.getViewportHeight()
+ : mProperties.getViewportHeight();
float scaleX = cacheWidth / viewportWidth;
float scaleY = cacheHeight / viewportHeight;
outCanvas.scale(scaleX, scaleY);
@@ -635,7 +621,7 @@ void Tree::onPropertyChanged(TreeProperties* prop) {
}
}
-}; // namespace VectorDrawable
+}; // namespace VectorDrawable
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index efbb695a14dd..da52a9503377 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -17,15 +17,15 @@
#ifndef ANDROID_HWUI_VPATH_H
#define ANDROID_HWUI_VPATH_H
-#include "hwui/Canvas.h"
+#include "DisplayList.h"
#include "hwui/Bitmap.h"
+#include "hwui/Canvas.h"
#include "renderthread/CacheManager.h"
-#include "DisplayList.h"
#include <SkBitmap.h>
+#include <SkCanvas.h>
#include <SkColor.h>
#include <SkColorFilter.h>
-#include <SkCanvas.h>
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkPath.h>
@@ -36,25 +36,35 @@
#include <cutils/compiler.h>
#include <stddef.h>
-#include <vector>
#include <string>
+#include <vector>
namespace android {
namespace uirenderer {
// Debug
#if DEBUG_VECTOR_DRAWABLE
- #define VECTOR_DRAWABLE_LOGD(...) ALOGD(__VA_ARGS__)
+#define VECTOR_DRAWABLE_LOGD(...) ALOGD(__VA_ARGS__)
#else
- #define VECTOR_DRAWABLE_LOGD(...)
+#define VECTOR_DRAWABLE_LOGD(...)
#endif
namespace VectorDrawable {
-#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false)
+#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) \
+ (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false)
#define VD_SET_PROP(field, value) ((value) != (field) ? ((field) = (value), true) : false)
-#define VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP((mPrimitiveFields.field), (value));\
- onPropertyChanged(); retVal;})
-#define UPDATE_SKPROP(field, value) ({bool retVal = ((field) != (value)); if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); retVal;})
+#define VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, value) \
+ ({ \
+ bool retVal = VD_SET_PROP((mPrimitiveFields.field), (value)); \
+ onPropertyChanged(); \
+ retVal; \
+ })
+#define UPDATE_SKPROP(field, value) \
+ ({ \
+ bool retVal = ((field) != (value)); \
+ if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); \
+ retVal; \
+ })
/* A VectorDrawable is composed of a tree of nodes.
* Each node can be a group node, or a path.
@@ -85,12 +95,9 @@ class PropertyChangedListener {
public:
PropertyChangedListener(bool* dirty, bool* stagingDirty)
: mDirty(dirty), mStagingDirty(stagingDirty) {}
- void onPropertyChanged() {
- *mDirty = true;
- }
- void onStagingPropertyChanged() {
- *mStagingDirty = true;
- }
+ void onPropertyChanged() { *mDirty = true; }
+ void onStagingPropertyChanged() { *mStagingDirty = true; }
+
private:
bool* mDirty;
bool* mStagingDirty;
@@ -101,27 +108,24 @@ public:
class Properties {
public:
explicit Properties(Node* node) : mNode(node) {}
- inline void onPropertyChanged() {
- mNode->onPropertyChanged(this);
- }
+ inline void onPropertyChanged() { mNode->onPropertyChanged(this); }
+
private:
Node* mNode;
};
- Node(const Node& node) {
- mName = node.mName;
- }
+ Node(const Node& node) { mName = node.mName; }
Node() {}
virtual void draw(SkCanvas* outCanvas, bool useStagingData) = 0;
virtual void dump() = 0;
- void setName(const char* name) {
- mName = name;
- }
+ void setName(const char* name) { mName = name; }
virtual void setPropertyChangedListener(PropertyChangedListener* listener) {
mPropertyChangedListener = listener;
}
virtual void onPropertyChanged(Properties* properties) = 0;
- virtual ~Node(){}
+ virtual ~Node() {}
virtual void syncProperties() = 0;
+ virtual void setAntiAlias(bool aa) = 0;
+
protected:
std::string mName;
PropertyChangedListener* mPropertyChangedListener = nullptr;
@@ -134,8 +138,7 @@ public:
std::vector<size_t> verbSizes;
std::vector<float> points;
bool operator==(const Data& data) const {
- return verbs == data.verbs && verbSizes == data.verbSizes
- && points == data.points;
+ return verbs == data.verbs && verbSizes == data.verbSizes && points == data.points;
}
};
@@ -156,11 +159,9 @@ public:
}
mData = data;
onPropertyChanged();
-
- }
- const Data& getData() const {
- return mData;
}
+ const Data& getData() const { return mData; }
+
private:
Data mData;
};
@@ -177,7 +178,7 @@ public:
if (mPropertyChangedListener) {
mPropertyChangedListener->onStagingPropertyChanged();
}
- } else if (prop == &mProperties){
+ } else if (prop == &mProperties) {
mSkPathDirty = true;
if (mPropertyChangedListener) {
mPropertyChangedListener->onPropertyChanged();
@@ -203,7 +204,7 @@ private:
bool mStagingPropertiesDirty = true;
};
-class ANDROID_API FullPath: public Path {
+class ANDROID_API FullPath : public Path {
public:
class FullPathProperties : public Properties {
public:
@@ -234,87 +235,59 @@ public:
onPropertyChanged();
}
void setFillGradient(SkShader* gradient) {
- if(UPDATE_SKPROP(fillGradient, gradient)) {
+ if (UPDATE_SKPROP(fillGradient, gradient)) {
onPropertyChanged();
}
}
void setStrokeGradient(SkShader* gradient) {
- if(UPDATE_SKPROP(strokeGradient, gradient)) {
+ if (UPDATE_SKPROP(strokeGradient, gradient)) {
onPropertyChanged();
}
}
- SkShader* getFillGradient() const {
- return fillGradient;
- }
- SkShader* getStrokeGradient() const {
- return strokeGradient;
- }
- float getStrokeWidth() const{
- return mPrimitiveFields.strokeWidth;
- }
+ SkShader* getFillGradient() const { return fillGradient; }
+ SkShader* getStrokeGradient() const { return strokeGradient; }
+ float getStrokeWidth() const { return mPrimitiveFields.strokeWidth; }
void setStrokeWidth(float strokeWidth) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth);
}
- SkColor getStrokeColor() const{
- return mPrimitiveFields.strokeColor;
- }
+ SkColor getStrokeColor() const { return mPrimitiveFields.strokeColor; }
void setStrokeColor(SkColor strokeColor) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeColor, strokeColor);
}
- float getStrokeAlpha() const{
- return mPrimitiveFields.strokeAlpha;
- }
+ float getStrokeAlpha() const { return mPrimitiveFields.strokeAlpha; }
void setStrokeAlpha(float strokeAlpha) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeAlpha, strokeAlpha);
}
- SkColor getFillColor() const {
- return mPrimitiveFields.fillColor;
- }
+ SkColor getFillColor() const { return mPrimitiveFields.fillColor; }
void setFillColor(SkColor fillColor) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillColor, fillColor);
}
- float getFillAlpha() const{
- return mPrimitiveFields.fillAlpha;
- }
+ float getFillAlpha() const { return mPrimitiveFields.fillAlpha; }
void setFillAlpha(float fillAlpha) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillAlpha, fillAlpha);
}
- float getTrimPathStart() const{
- return mPrimitiveFields.trimPathStart;
- }
+ float getTrimPathStart() const { return mPrimitiveFields.trimPathStart; }
void setTrimPathStart(float trimPathStart) {
VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathStart, trimPathStart, mTrimDirty);
}
- float getTrimPathEnd() const{
- return mPrimitiveFields.trimPathEnd;
- }
+ float getTrimPathEnd() const { return mPrimitiveFields.trimPathEnd; }
void setTrimPathEnd(float trimPathEnd) {
VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathEnd, trimPathEnd, mTrimDirty);
}
- float getTrimPathOffset() const{
- return mPrimitiveFields.trimPathOffset;
- }
+ float getTrimPathOffset() const { return mPrimitiveFields.trimPathOffset; }
void setTrimPathOffset(float trimPathOffset) {
VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathOffset, trimPathOffset, mTrimDirty);
}
- float getStrokeMiterLimit() const {
- return mPrimitiveFields.strokeMiterLimit;
- }
- float getStrokeLineCap() const {
- return mPrimitiveFields.strokeLineCap;
- }
- float getStrokeLineJoin() const {
- return mPrimitiveFields.strokeLineJoin;
- }
- float getFillType() const {
- return mPrimitiveFields.fillType;
- }
+ float getStrokeMiterLimit() const { return mPrimitiveFields.strokeMiterLimit; }
+ float getStrokeLineCap() const { return mPrimitiveFields.strokeLineCap; }
+ float getStrokeLineJoin() const { return mPrimitiveFields.strokeLineJoin; }
+ float getFillType() const { return mPrimitiveFields.fillType; }
bool copyProperties(int8_t* outProperties, int length) const;
void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
- SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
- float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
- int fillType) {
+ SkColor fillColor, float fillAlpha, float trimPathStart,
+ float trimPathEnd, float trimPathOffset, float strokeMiterLimit,
+ int strokeLineCap, int strokeLineJoin, int fillType) {
mPrimitiveFields.strokeWidth = strokeWidth;
mPrimitiveFields.strokeColor = strokeColor;
mPrimitiveFields.strokeAlpha = strokeAlpha;
@@ -334,6 +307,7 @@ public:
void setColorPropertyValue(int propertyId, int32_t value);
void setPropertyValue(int propertyId, float value);
bool mTrimDirty;
+
private:
enum class Property {
strokeWidth = 0,
@@ -356,7 +330,7 @@ public:
};
// Called from UI thread
- FullPath(const FullPath& path); // for cloning
+ FullPath(const FullPath& path); // for cloning
FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
FullPath() : Path() {}
void draw(SkCanvas* outCanvas, bool useStagingData) override;
@@ -381,29 +355,32 @@ public:
}
}
}
+ virtual void setAntiAlias(bool aa) { mAntiAlias = aa; }
protected:
const SkPath& getUpdatedPath(bool useStagingData, SkPath* tempStagingPath) override;
-private:
+private:
FullPathProperties mProperties = FullPathProperties(this);
FullPathProperties mStagingProperties = FullPathProperties(this);
bool mStagingPropertiesDirty = true;
// Intermediate data for drawing, render thread only
SkPath mTrimmedSkPath;
-
+ // Default to use AntiAlias
+ bool mAntiAlias = true;
};
-class ANDROID_API ClipPath: public Path {
+class ANDROID_API ClipPath : public Path {
public:
ClipPath(const ClipPath& path) : Path(path) {}
ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
ClipPath() : Path() {}
void draw(SkCanvas* outCanvas, bool useStagingData) override;
+ virtual void setAntiAlias(bool aa) {}
};
-class ANDROID_API Group: public Node {
+class ANDROID_API Group : public Node {
public:
class GroupProperties : public Properties {
public:
@@ -421,50 +398,26 @@ public:
mPrimitiveFields = prop.mPrimitiveFields;
onPropertyChanged();
}
- float getRotation() const {
- return mPrimitiveFields.rotate;
- }
- void setRotation(float rotation) {
- VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(rotate, rotation);
- }
- float getPivotX() const {
- return mPrimitiveFields.pivotX;
- }
- void setPivotX(float pivotX) {
- VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotX, pivotX);
- }
- float getPivotY() const {
- return mPrimitiveFields.pivotY;
- }
- void setPivotY(float pivotY) {
- VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotY, pivotY);
- }
- float getScaleX() const {
- return mPrimitiveFields.scaleX;
- }
- void setScaleX(float scaleX) {
- VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleX, scaleX);
- }
- float getScaleY() const {
- return mPrimitiveFields.scaleY;
- }
- void setScaleY(float scaleY) {
- VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleY, scaleY);
- }
- float getTranslateX() const {
- return mPrimitiveFields.translateX;
- }
+ float getRotation() const { return mPrimitiveFields.rotate; }
+ void setRotation(float rotation) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(rotate, rotation); }
+ float getPivotX() const { return mPrimitiveFields.pivotX; }
+ void setPivotX(float pivotX) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotX, pivotX); }
+ float getPivotY() const { return mPrimitiveFields.pivotY; }
+ void setPivotY(float pivotY) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotY, pivotY); }
+ float getScaleX() const { return mPrimitiveFields.scaleX; }
+ void setScaleX(float scaleX) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleX, scaleX); }
+ float getScaleY() const { return mPrimitiveFields.scaleY; }
+ void setScaleY(float scaleY) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleY, scaleY); }
+ float getTranslateX() const { return mPrimitiveFields.translateX; }
void setTranslateX(float translateX) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateX, translateX);
}
- float getTranslateY() const {
- return mPrimitiveFields.translateY;
- }
+ float getTranslateY() const { return mPrimitiveFields.translateY; }
void setTranslateY(float translateY) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateY, translateY);
}
- void updateProperties(float rotate, float pivotX, float pivotY,
- float scaleX, float scaleY, float translateX, float translateY) {
+ void updateProperties(float rotate, float pivotX, float pivotY, float scaleX, float scaleY,
+ float translateX, float translateY) {
mPrimitiveFields.rotate = rotate;
mPrimitiveFields.pivotX = pivotX;
mPrimitiveFields.pivotY = pivotY;
@@ -478,6 +431,7 @@ public:
float getPropertyValue(int propertyId) const;
bool copyProperties(float* outProperties, int length) const;
static bool isValidProperty(int propertyId);
+
private:
enum class Property {
rotate = 0,
@@ -498,7 +452,7 @@ public:
virtual void setPropertyChangedListener(PropertyChangedListener* listener) override {
Node::setPropertyChangedListener(listener);
for (auto& child : mChildren) {
- child->setPropertyChangedListener(listener);
+ child->setPropertyChangedListener(listener);
}
}
virtual void syncProperties() override;
@@ -527,11 +481,17 @@ public:
}
}
+ virtual void setAntiAlias(bool aa) {
+ for (auto& child : mChildren) {
+ child->setAntiAlias(aa);
+ }
+ }
+
private:
GroupProperties mProperties = GroupProperties(this);
GroupProperties mStagingProperties = GroupProperties(this);
bool mStagingPropertiesDirty = true;
- std::vector< std::unique_ptr<Node> > mChildren;
+ std::vector<std::unique_ptr<Node> > mChildren;
};
class ANDROID_API Tree : public VirtualLightRefBase {
@@ -547,17 +507,25 @@ public:
}
// Draws the VD onto a bitmap cache, then the bitmap cache will be rendered onto the input
// canvas. Returns the number of pixels needed for the bitmap cache.
- int draw(Canvas* outCanvas, SkColorFilter* colorFilter,
- const SkRect& bounds, bool needsMirroring, bool canReuseCache);
+ int draw(Canvas* outCanvas, SkColorFilter* colorFilter, const SkRect& bounds,
+ bool needsMirroring, bool canReuseCache);
void drawStaging(Canvas* canvas);
Bitmap& getBitmapUpdateIfDirty();
- void setAllowCaching(bool allowCaching) {
- mAllowCaching = allowCaching;
- }
+ void setAllowCaching(bool allowCaching) { mAllowCaching = allowCaching; }
SkPaint* getPaint();
void syncProperties() {
if (mStagingProperties.mNonAnimatablePropertiesDirty) {
+ mCache.dirty |= (mProperties.mNonAnimatableProperties.viewportWidth !=
+ mStagingProperties.mNonAnimatableProperties.viewportWidth) ||
+ (mProperties.mNonAnimatableProperties.viewportHeight !=
+ mStagingProperties.mNonAnimatableProperties.viewportHeight) ||
+ (mProperties.mNonAnimatableProperties.scaledWidth !=
+ mStagingProperties.mNonAnimatableProperties.scaledWidth) ||
+ (mProperties.mNonAnimatableProperties.scaledHeight !=
+ mStagingProperties.mNonAnimatableProperties.scaledHeight) ||
+ (mProperties.mNonAnimatableProperties.bounds !=
+ mStagingProperties.mNonAnimatableProperties.bounds);
mProperties.syncNonAnimatableProperties(mStagingProperties);
mStagingProperties.mNonAnimatablePropertiesDirty = false;
}
@@ -583,9 +551,7 @@ public:
int scaledWidth = 0;
int scaledHeight = 0;
SkColorFilter* colorFilter = nullptr;
- ~NonAnimatableProperties() {
- SkSafeUnref(colorFilter);
- }
+ ~NonAnimatableProperties() { SkSafeUnref(colorFilter); }
} mNonAnimatableProperties;
bool mNonAnimatablePropertiesDirty = true;
@@ -596,14 +562,14 @@ public:
// Copy over the data that can only be changed in UI thread
if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) {
SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter,
- prop.mNonAnimatableProperties.colorFilter);
+ prop.mNonAnimatableProperties.colorFilter);
}
mNonAnimatableProperties = prop.mNonAnimatableProperties;
}
void setViewportSize(float width, float height) {
- if (mNonAnimatableProperties.viewportWidth != width
- || mNonAnimatableProperties.viewportHeight != height) {
+ if (mNonAnimatableProperties.viewportWidth != width ||
+ mNonAnimatableProperties.viewportHeight != height) {
mNonAnimatablePropertiesDirty = true;
mNonAnimatableProperties.viewportWidth = width;
mNonAnimatableProperties.viewportHeight = height;
@@ -622,12 +588,12 @@ public:
// If the requested size is bigger than what the bitmap was, then
// we increase the bitmap size to match. The width and height
// are bound by MAX_CACHED_BITMAP_SIZE.
- if (mNonAnimatableProperties.scaledWidth < width
- || mNonAnimatableProperties.scaledHeight < height) {
- mNonAnimatableProperties.scaledWidth = std::max(width,
- mNonAnimatableProperties.scaledWidth);
- mNonAnimatableProperties.scaledHeight = std::max(height,
- mNonAnimatableProperties.scaledHeight);
+ if (mNonAnimatableProperties.scaledWidth < width ||
+ mNonAnimatableProperties.scaledHeight < height) {
+ mNonAnimatableProperties.scaledWidth =
+ std::max(width, mNonAnimatableProperties.scaledWidth);
+ mNonAnimatableProperties.scaledHeight =
+ std::max(height, mNonAnimatableProperties.scaledHeight);
mNonAnimatablePropertiesDirty = true;
mTree->onPropertyChanged(this);
}
@@ -638,25 +604,13 @@ public:
mTree->onPropertyChanged(this);
}
}
- SkColorFilter* getColorFilter() const{
- return mNonAnimatableProperties.colorFilter;
- }
+ SkColorFilter* getColorFilter() const { return mNonAnimatableProperties.colorFilter; }
- float getViewportWidth() const {
- return mNonAnimatableProperties.viewportWidth;
- }
- float getViewportHeight() const {
- return mNonAnimatableProperties.viewportHeight;
- }
- float getScaledWidth() const {
- return mNonAnimatableProperties.scaledWidth;
- }
- float getScaledHeight() const {
- return mNonAnimatableProperties.scaledHeight;
- }
- void syncAnimatableProperties(const TreeProperties& prop) {
- mRootAlpha = prop.mRootAlpha;
- }
+ float getViewportWidth() const { return mNonAnimatableProperties.viewportWidth; }
+ float getViewportHeight() const { return mNonAnimatableProperties.viewportHeight; }
+ float getScaledWidth() const { return mNonAnimatableProperties.scaledWidth; }
+ float getScaledHeight() const { return mNonAnimatableProperties.scaledHeight; }
+ void syncAnimatableProperties(const TreeProperties& prop) { mRootAlpha = prop.mRootAlpha; }
bool setRootAlpha(float rootAlpha) {
if (rootAlpha != mRootAlpha) {
mAnimatablePropertiesDirty = true;
@@ -666,10 +620,8 @@ public:
}
return false;
}
- float getRootAlpha() const { return mRootAlpha;}
- const SkRect& getBounds() const {
- return mNonAnimatableProperties.bounds;
- }
+ float getRootAlpha() const { return mRootAlpha; }
+ const SkRect& getBounds() const { return mNonAnimatableProperties.bounds; }
Tree* mTree;
};
void onPropertyChanged(TreeProperties* prop);
@@ -692,7 +644,7 @@ public:
* Draws VD cache into a canvas. This should always be called from RT and it works with Skia
* pipelines only.
*/
- void draw(SkCanvas* canvas);
+ void draw(SkCanvas* canvas, const SkRect& bounds);
/**
* Draws VD into a GPU backed surface.
@@ -700,11 +652,13 @@ public:
*/
void updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context);
+ void setAntiAlias(bool aa) { mRootNode->setAntiAlias(aa); }
+
private:
class Cache {
public:
- sk_sp<Bitmap> bitmap; //used by HWUI pipeline and software
- //TODO: use surface instead of bitmap when drawing in software canvas
+ sk_sp<Bitmap> bitmap; // used by HWUI pipeline and software
+ // TODO: use surface instead of bitmap when drawing in software canvas
bool dirty = true;
// the rest of the code in Cache is used by Skia pipelines only
@@ -715,7 +669,7 @@ private:
* Stores a weak pointer to the atlas and a key.
*/
void setAtlas(sp<skiapipeline::VectorDrawableAtlas> atlas,
- skiapipeline::AtlasKey newAtlasKey);
+ skiapipeline::AtlasKey newAtlasKey);
/**
* Gets a surface and bounds from the atlas.
@@ -728,6 +682,7 @@ private:
* Releases atlas key from the atlas, which makes it available for reuse.
*/
void clear();
+
private:
wp<skiapipeline::VectorDrawableAtlas> mAtlas;
skiapipeline::AtlasKey mAtlasKey = INVALID_ATLAS_KEY;
@@ -738,11 +693,6 @@ private:
bool canReuseBitmap(Bitmap*, int width, int height);
void updateBitmapCache(Bitmap& outCache, bool useStagingData);
- /**
- * Draws the root node into "surface" at a given "dst" position.
- */
- void draw(SkSurface* surface, const SkRect& dst);
-
// Cap the bitmap size, such that it won't hurt the performance too much
// and it won't crash due to a very large scale.
// The drawable will look blurry above this size.
@@ -759,16 +709,16 @@ private:
Cache mStagingCache;
Cache mCache;
- PropertyChangedListener mPropertyChangedListener
- = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty);
+ PropertyChangedListener mPropertyChangedListener =
+ PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty);
mutable bool mWillBeConsumed = false;
};
-} // namespace VectorDrawable
+} // namespace VectorDrawable
typedef VectorDrawable::Path::Data PathData;
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
-#endif // ANDROID_HWUI_VPATH_H
+#endif // ANDROID_HWUI_VPATH_H
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index db982ad0c8f4..186d0a88a33e 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -45,15 +45,13 @@ struct Vertex {
vertex->y = y;
}
- static inline void set(Vertex* vertex, Vector2 val) {
- set(vertex, val.x, val.y);
- }
+ static inline void set(Vertex* vertex, Vector2 val) { set(vertex, val.x, val.y); }
static inline void copyWithOffset(Vertex* vertex, const Vertex& src, float x, float y) {
set(vertex, src.x + x, src.y + y);
}
-}; // struct Vertex
+}; // struct Vertex
REQUIRE_COMPATIBLE_LAYOUT(Vertex);
@@ -65,14 +63,14 @@ struct TextureVertex {
float u, v;
static inline void set(TextureVertex* vertex, float x, float y, float u, float v) {
- *vertex = { x, y, u, v };
+ *vertex = {x, y, u, v};
}
static inline void setUV(TextureVertex* vertex, float u, float v) {
vertex[0].u = u;
vertex[0].v = v;
}
-}; // struct TextureVertex
+}; // struct TextureVertex
REQUIRE_COMPATIBLE_LAYOUT(TextureVertex);
@@ -83,15 +81,15 @@ REQUIRE_COMPATIBLE_LAYOUT(TextureVertex);
struct ColorTextureVertex {
float x, y;
float u, v;
- float r, g, b, a; // pre-multiplied linear
+ float r, g, b, a; // pre-multiplied linear
- static inline void set(ColorTextureVertex* vertex, float x, float y,
- float u, float v, uint32_t color) {
+ static inline void set(ColorTextureVertex* vertex, float x, float y, float u, float v,
+ uint32_t color) {
FloatColor c;
c.set(color);
- *vertex = { x, y, u, v, c.r, c.g, c.b, c.a };
+ *vertex = {x, y, u, v, c.r, c.g, c.b, c.a};
}
-}; // struct ColorTextureVertex
+}; // struct ColorTextureVertex
REQUIRE_COMPATIBLE_LAYOUT(ColorTextureVertex);
@@ -103,22 +101,20 @@ struct AlphaVertex {
float alpha;
static inline void set(AlphaVertex* vertex, float x, float y, float alpha) {
- *vertex = { x, y, alpha };
+ *vertex = {x, y, alpha};
}
- static inline void copyWithOffset(AlphaVertex* vertex, const AlphaVertex& src,
- float x, float y) {
+ static inline void copyWithOffset(AlphaVertex* vertex, const AlphaVertex& src, float x,
+ float y) {
AlphaVertex::set(vertex, src.x + x, src.y + y, src.alpha);
}
- static inline void setColor(AlphaVertex* vertex, float alpha) {
- vertex[0].alpha = alpha;
- }
-}; // struct AlphaVertex
+ static inline void setColor(AlphaVertex* vertex, float alpha) { vertex[0].alpha = alpha; }
+}; // struct AlphaVertex
REQUIRE_COMPATIBLE_LAYOUT(AlphaVertex);
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_VERTEX_H
+#endif // ANDROID_HWUI_VERTEX_H
diff --git a/libs/hwui/VertexBuffer.h b/libs/hwui/VertexBuffer.h
index bdb5b7b381bf..613cf4af64b2 100644
--- a/libs/hwui/VertexBuffer.h
+++ b/libs/hwui/VertexBuffer.h
@@ -41,8 +41,7 @@ public:
, mMeshFeatureFlags(kNone)
, mReallocBuffer(nullptr)
, mCleanupMethod(nullptr)
- , mCleanupIndexMethod(nullptr)
- {}
+ , mCleanupIndexMethod(nullptr) {}
~VertexBuffer() {
if (mCleanupMethod) mCleanupMethod(mBuffer);
@@ -128,10 +127,10 @@ public:
unsigned int getVertexCount() const { return mVertexCount; }
unsigned int getSize() const { return mByteCount; }
unsigned int getIndexCount() const { return mIndexCount; }
- void updateIndexCount(unsigned int newCount) {
+ void updateIndexCount(unsigned int newCount) {
mIndexCount = std::min(newCount, mAllocatedIndexCount);
}
- void updateVertexCount(unsigned int newCount) {
+ void updateVertexCount(unsigned int newCount) {
mVertexCount = std::min(newCount, mAllocatedVertexCount);
}
MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
@@ -153,7 +152,7 @@ public:
private:
template <class TYPE>
static void cleanup(void* buffer) {
- delete[] (TYPE*)buffer;
+ delete[](TYPE*) buffer;
}
Rect mBounds;
@@ -169,13 +168,13 @@ private:
MeshFeatureFlags mMeshFeatureFlags;
- void* mReallocBuffer; // used for multi-allocation
+ void* mReallocBuffer; // used for multi-allocation
void (*mCleanupMethod)(void*);
void (*mCleanupIndexMethod)(void*);
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_VERTEX_BUFFER_H
+#endif // ANDROID_HWUI_VERTEX_BUFFER_H
diff --git a/libs/hwui/VkLayer.cpp b/libs/hwui/VkLayer.cpp
index ef4784b3d65b..30fba7ae7d9b 100644
--- a/libs/hwui/VkLayer.cpp
+++ b/libs/hwui/VkLayer.cpp
@@ -36,5 +36,5 @@ void VkLayer::onVkContextDestroyed() {
mImage = nullptr;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h
index 7e41ad1d0e9c..e9664d04b7a5 100644
--- a/libs/hwui/VkLayer.h
+++ b/libs/hwui/VkLayer.h
@@ -28,7 +28,7 @@ namespace uirenderer {
class VkLayer : public Layer {
public:
VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
- SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend)
+ sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend)
: Layer(renderState, Api::Vulkan, colorFilter, alpha, mode)
, mWidth(layerWidth)
, mHeight(layerHeight)
@@ -36,30 +36,20 @@ public:
virtual ~VkLayer() {}
- uint32_t getWidth() const override {
- return mWidth;
- }
+ uint32_t getWidth() const override { return mWidth; }
- uint32_t getHeight() const override {
- return mHeight;
- }
+ uint32_t getHeight() const override { return mHeight; }
void setSize(uint32_t width, uint32_t height) override {
mWidth = width;
mHeight = height;
}
- void setBlend(bool blend) override {
- mBlend = blend;
- }
+ void setBlend(bool blend) override { mBlend = blend; }
- bool isBlend() const override {
- return mBlend;
- }
+ bool isBlend() const override { return mBlend; }
- sk_sp<SkImage> getImage() {
- return mImage;
- }
+ sk_sp<SkImage> getImage() { return mImage; }
void updateTexture();
@@ -72,9 +62,9 @@ private:
int mHeight;
bool mBlend;
- sk_sp<SkImage> mImage;
+ sk_sp<SkImage> mImage;
-}; // struct VkLayer
+}; // struct VkLayer
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/debug/DefaultGlesDriver.cpp b/libs/hwui/debug/DefaultGlesDriver.cpp
index 4515ec1f25a5..46ab20081d17 100644
--- a/libs/hwui/debug/DefaultGlesDriver.cpp
+++ b/libs/hwui/debug/DefaultGlesDriver.cpp
@@ -35,6 +35,6 @@ namespace debug {
#undef CALL_GL_API
#undef CALL_GL_API_RETURN
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/DefaultGlesDriver.h b/libs/hwui/debug/DefaultGlesDriver.h
index 3eab97077004..8027ea284aaa 100644
--- a/libs/hwui/debug/DefaultGlesDriver.h
+++ b/libs/hwui/debug/DefaultGlesDriver.h
@@ -25,11 +25,10 @@ namespace debug {
class DefaultGlesDriver : public GlesDriver {
public:
#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) override;
- #include "gles_decls.in"
+#include "gles_decls.in"
#undef GL_ENTRY
-
};
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/FatalBaseDriver.cpp b/libs/hwui/debug/FatalBaseDriver.cpp
index 4c38fac33521..ed0f8316d208 100644
--- a/libs/hwui/debug/FatalBaseDriver.cpp
+++ b/libs/hwui/debug/FatalBaseDriver.cpp
@@ -25,9 +25,9 @@ namespace debug {
// Generate the proxy
#define API_ENTRY(x) FatalBaseDriver::x##_
#define CALL_GL_API(x, ...) LOG_ALWAYS_FATAL("Not Implemented");
-#define CALL_GL_API_RETURN(x, ...) \
- LOG_ALWAYS_FATAL("Not Implemented"); \
- return static_cast<decltype(x(__VA_ARGS__))>(0);
+#define CALL_GL_API_RETURN(x, ...) \
+ LOG_ALWAYS_FATAL("Not Implemented"); \
+ return static_cast<decltype(x(__VA_ARGS__))>(0);
#include "gles_stubs.in"
@@ -35,6 +35,6 @@ namespace debug {
#undef CALL_GL_API
#undef CALL_GL_API_RETURN
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/FatalBaseDriver.h b/libs/hwui/debug/FatalBaseDriver.h
index 76c30e90bd39..45353d0568aa 100644
--- a/libs/hwui/debug/FatalBaseDriver.h
+++ b/libs/hwui/debug/FatalBaseDriver.h
@@ -28,10 +28,10 @@ namespace debug {
class FatalBaseDriver : public GlesDriver {
public:
#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) override;
- #include "gles_decls.in"
+#include "gles_decls.in"
#undef GL_ENTRY
};
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesDriver.cpp b/libs/hwui/debug/GlesDriver.cpp
index 97e8f3a81b74..98f06b0cb4f0 100644
--- a/libs/hwui/debug/GlesDriver.cpp
+++ b/libs/hwui/debug/GlesDriver.cpp
@@ -41,6 +41,6 @@ sk_sp<const GrGLInterface> GlesDriver::getSkiaInterface() {
return skiaInterface;
}
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesDriver.h b/libs/hwui/debug/GlesDriver.h
index 3c36487f72cf..1c77c1a45b82 100644
--- a/libs/hwui/debug/GlesDriver.h
+++ b/libs/hwui/debug/GlesDriver.h
@@ -43,13 +43,13 @@ public:
virtual sk_sp<const GrGLInterface> getSkiaInterface();
#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) = 0;
- #include "gles_decls.in"
+#include "gles_decls.in"
#undef GL_ENTRY
static GlesDriver* get();
static std::unique_ptr<GlesDriver> replace(std::unique_ptr<GlesDriver>&& driver);
};
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesErrorCheckWrapper.cpp b/libs/hwui/debug/GlesErrorCheckWrapper.cpp
index 7ededaaa7fc2..8d11c1905da3 100644
--- a/libs/hwui/debug/GlesErrorCheckWrapper.cpp
+++ b/libs/hwui/debug/GlesErrorCheckWrapper.cpp
@@ -29,38 +29,39 @@ void GlesErrorCheckWrapper::assertNoErrors(const char* apicall) {
while ((status = mBase.glGetError_()) != GL_NO_ERROR) {
lastError = status;
switch (status) {
- case GL_INVALID_ENUM:
- ALOGE("GL error: GL_INVALID_ENUM");
- lastErrorName = "GL_INVALID_ENUM";
- break;
- case GL_INVALID_VALUE:
- ALOGE("GL error: GL_INVALID_VALUE");
- lastErrorName = "GL_INVALID_VALUE";
- break;
- case GL_INVALID_OPERATION:
- ALOGE("GL error: GL_INVALID_OPERATION");
- lastErrorName = "GL_INVALID_OPERATION";
- break;
- case GL_OUT_OF_MEMORY:
- ALOGE("GL error: Out of memory!");
- lastErrorName = "GL_OUT_OF_MEMORY";
- break;
- default:
- ALOGE("GL error: 0x%x", status);
- lastErrorName = "UNKNOWN";
+ case GL_INVALID_ENUM:
+ ALOGE("GL error: GL_INVALID_ENUM");
+ lastErrorName = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ ALOGE("GL error: GL_INVALID_VALUE");
+ lastErrorName = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ ALOGE("GL error: GL_INVALID_OPERATION");
+ lastErrorName = "GL_INVALID_OPERATION";
+ break;
+ case GL_OUT_OF_MEMORY:
+ ALOGE("GL error: Out of memory!");
+ lastErrorName = "GL_OUT_OF_MEMORY";
+ break;
+ default:
+ ALOGE("GL error: 0x%x", status);
+ lastErrorName = "UNKNOWN";
}
}
- LOG_ALWAYS_FATAL_IF(lastError != GL_NO_ERROR,
- "%s error! %s (0x%x)", apicall, lastErrorName, lastError);
+ LOG_ALWAYS_FATAL_IF(lastError != GL_NO_ERROR, "%s error! %s (0x%x)", apicall, lastErrorName,
+ lastError);
}
#define API_ENTRY(x) GlesErrorCheckWrapper::x##_
-#define CALL_GL_API(x, ...) \
- mBase.x##_(__VA_ARGS__); assertNoErrors(#x)
+#define CALL_GL_API(x, ...) \
+ mBase.x##_(__VA_ARGS__); \
+ assertNoErrors(#x)
-#define CALL_GL_API_RETURN(x, ...) \
+#define CALL_GL_API_RETURN(x, ...) \
auto ret = mBase.x##_(__VA_ARGS__); \
- assertNoErrors(#x); \
+ assertNoErrors(#x); \
return ret
#include "gles_stubs.in"
@@ -69,6 +70,6 @@ void GlesErrorCheckWrapper::assertNoErrors(const char* apicall) {
#undef CALL_GL_API
#undef CALL_GL_API_RETURN
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesErrorCheckWrapper.h b/libs/hwui/debug/GlesErrorCheckWrapper.h
index fd45fc0184a1..ee5cc1f46de8 100644
--- a/libs/hwui/debug/GlesErrorCheckWrapper.h
+++ b/libs/hwui/debug/GlesErrorCheckWrapper.h
@@ -27,7 +27,7 @@ public:
GlesErrorCheckWrapper(GlesDriver& base) : mBase(base) {}
#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) override;
- #include "gles_decls.in"
+#include "gles_decls.in"
#undef GL_ENTRY
private:
@@ -36,6 +36,6 @@ private:
GlesDriver& mBase;
};
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/MockGlesDriver.h b/libs/hwui/debug/MockGlesDriver.h
index e0bfc5780b21..e48ca193d48f 100644
--- a/libs/hwui/debug/MockGlesDriver.h
+++ b/libs/hwui/debug/MockGlesDriver.h
@@ -27,10 +27,11 @@ namespace debug {
class MockGlesDriver : public FatalBaseDriver {
public:
MOCK_METHOD2(glBindBuffer_, void(GLenum target, GLuint buffer));
- MOCK_METHOD4(glBufferData_, void(GLenum target, GLsizeiptr size, const void *data, GLenum usage));
- MOCK_METHOD2(glGenBuffers_, void(GLsizei n, GLuint *buffers));
+ MOCK_METHOD4(glBufferData_,
+ void(GLenum target, GLsizeiptr size, const void* data, GLenum usage));
+ MOCK_METHOD2(glGenBuffers_, void(GLsizei n, GLuint* buffers));
};
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/NullGlesDriver.cpp b/libs/hwui/debug/NullGlesDriver.cpp
index 8fbe4bfe7033..212b24290e22 100644
--- a/libs/hwui/debug/NullGlesDriver.cpp
+++ b/libs/hwui/debug/NullGlesDriver.cpp
@@ -29,27 +29,27 @@ struct {
GLboolean scissorEnabled;
} gState;
-static void nullglGenCommon(GLsizei n, GLuint *buffers) {
+static void nullglGenCommon(GLsizei n, GLuint* buffers) {
static GLuint nextId = 0;
int i;
- for(i = 0; i < n; i++) {
+ for (i = 0; i < n; i++) {
buffers[i] = ++nextId;
}
}
-void NullGlesDriver::glGenBuffers_(GLsizei n, GLuint *buffers) {
+void NullGlesDriver::glGenBuffers_(GLsizei n, GLuint* buffers) {
nullglGenCommon(n, buffers);
}
-void NullGlesDriver::glGenFramebuffers_(GLsizei n, GLuint *framebuffers) {
+void NullGlesDriver::glGenFramebuffers_(GLsizei n, GLuint* framebuffers) {
nullglGenCommon(n, framebuffers);
}
-void NullGlesDriver::glGenRenderbuffers_(GLsizei n, GLuint *renderbuffers) {
+void NullGlesDriver::glGenRenderbuffers_(GLsizei n, GLuint* renderbuffers) {
nullglGenCommon(n, renderbuffers);
}
-void NullGlesDriver::glGenTextures_(GLsizei n, GLuint *textures) {
+void NullGlesDriver::glGenTextures_(GLsizei n, GLuint* textures) {
nullglGenCommon(n, textures);
}
@@ -63,35 +63,37 @@ GLuint NullGlesDriver::glCreateShader_(GLenum type) {
return ++nextShader;
}
-void NullGlesDriver::glGetProgramiv_(GLuint program, GLenum pname, GLint *params) {
+void NullGlesDriver::glGetProgramiv_(GLuint program, GLenum pname, GLint* params) {
switch (pname) {
- case GL_DELETE_STATUS:
- case GL_LINK_STATUS:
- case GL_VALIDATE_STATUS:
- *params = GL_TRUE;
- break;
- case GL_INFO_LOG_LENGTH:
- *params = 16;
- break;
+ case GL_DELETE_STATUS:
+ case GL_LINK_STATUS:
+ case GL_VALIDATE_STATUS:
+ *params = GL_TRUE;
+ break;
+ case GL_INFO_LOG_LENGTH:
+ *params = 16;
+ break;
}
}
-void NullGlesDriver::glGetProgramInfoLog_(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+void NullGlesDriver::glGetProgramInfoLog_(GLuint program, GLsizei bufSize, GLsizei* length,
+ GLchar* infoLog) {
*length = snprintf(infoLog, bufSize, "success");
if (*length >= bufSize) {
*length = bufSize - 1;
}
}
-void NullGlesDriver::glGetShaderiv_(GLuint shader, GLenum pname, GLint *params) {
+void NullGlesDriver::glGetShaderiv_(GLuint shader, GLenum pname, GLint* params) {
switch (pname) {
- case GL_COMPILE_STATUS:
- case GL_DELETE_STATUS:
- *params = GL_TRUE;
+ case GL_COMPILE_STATUS:
+ case GL_DELETE_STATUS:
+ *params = GL_TRUE;
}
}
-void NullGlesDriver::glGetShaderInfoLog_(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+void NullGlesDriver::glGetShaderInfoLog_(GLuint shader, GLsizei bufSize, GLsizei* length,
+ GLchar* infoLog) {
*length = snprintf(infoLog, bufSize, "success");
if (*length >= bufSize) {
*length = bufSize - 1;
@@ -100,9 +102,9 @@ void NullGlesDriver::glGetShaderInfoLog_(GLuint shader, GLsizei bufSize, GLsizei
void setBooleanState(GLenum cap, GLboolean value) {
switch (cap) {
- case GL_SCISSOR_TEST:
- gState.scissorEnabled = value;
- break;
+ case GL_SCISSOR_TEST:
+ gState.scissorEnabled = value;
+ break;
}
}
@@ -116,55 +118,55 @@ void NullGlesDriver::glDisable_(GLenum cap) {
GLboolean NullGlesDriver::glIsEnabled_(GLenum cap) {
switch (cap) {
- case GL_SCISSOR_TEST:
- return gState.scissorEnabled;
- default:
- return GL_FALSE;
+ case GL_SCISSOR_TEST:
+ return gState.scissorEnabled;
+ default:
+ return GL_FALSE;
}
}
-void NullGlesDriver::glGetIntegerv_(GLenum pname, GLint *data) {
+void NullGlesDriver::glGetIntegerv_(GLenum pname, GLint* data) {
switch (pname) {
- case GL_MAX_TEXTURE_SIZE:
- *data = 2048;
- break;
- case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
- *data = 4;
- break;
- default:
- *data = 0;
+ case GL_MAX_TEXTURE_SIZE:
+ *data = 2048;
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ *data = 4;
+ break;
+ default:
+ *data = 0;
}
}
GLenum NullGlesDriver::glCheckFramebufferStatus_(GLenum target) {
switch (target) {
- case GL_FRAMEBUFFER:
- return GL_FRAMEBUFFER_COMPLETE;
- default:
- return 0; // error case
+ case GL_FRAMEBUFFER:
+ return GL_FRAMEBUFFER_COMPLETE;
+ default:
+ return 0; // error case
}
}
static const char* getString(GLenum name) {
switch (name) {
- case GL_VENDOR:
- return "android";
- case GL_RENDERER:
- return "null";
- case GL_VERSION:
- return "OpenGL ES 2.0 rev1";
- case GL_SHADING_LANGUAGE_VERSION:
- return "OpenGL ES GLSL ES 2.0 rev1";
- case GL_EXTENSIONS:
- default:
- return "";
+ case GL_VENDOR:
+ return "android";
+ case GL_RENDERER:
+ return "null";
+ case GL_VERSION:
+ return "OpenGL ES 2.0 rev1";
+ case GL_SHADING_LANGUAGE_VERSION:
+ return "OpenGL ES GLSL ES 2.0 rev1";
+ case GL_EXTENSIONS:
+ default:
+ return "";
}
}
const GLubyte* NullGlesDriver::glGetString_(GLenum name) {
- return (GLubyte*) getString(name);
+ return (GLubyte*)getString(name);
}
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/NullGlesDriver.h b/libs/hwui/debug/NullGlesDriver.h
index 37ca8f34f87b..1a27dbc35299 100644
--- a/libs/hwui/debug/NullGlesDriver.h
+++ b/libs/hwui/debug/NullGlesDriver.h
@@ -26,26 +26,28 @@ class NullGlesDriver : public FatalBaseDriver {
public:
virtual sk_sp<const GrGLInterface> getSkiaInterface() override;
- virtual void glGenBuffers_(GLsizei n, GLuint *buffers) override;
- virtual void glGenFramebuffers_(GLsizei n, GLuint *framebuffers) override;
- virtual void glGenRenderbuffers_(GLsizei n, GLuint *renderbuffers) override;
- virtual void glGenTextures_(GLsizei n, GLuint *textures) override;
+ virtual void glGenBuffers_(GLsizei n, GLuint* buffers) override;
+ virtual void glGenFramebuffers_(GLsizei n, GLuint* framebuffers) override;
+ virtual void glGenRenderbuffers_(GLsizei n, GLuint* renderbuffers) override;
+ virtual void glGenTextures_(GLsizei n, GLuint* textures) override;
virtual GLuint glCreateProgram_(void) override;
virtual GLuint glCreateShader_(GLenum type) override;
- virtual void glGetProgramiv_(GLuint program, GLenum pname, GLint *params) override;
- virtual void glGetProgramInfoLog_(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) override;
- virtual void glGetShaderiv_(GLuint shader, GLenum pname, GLint *params) override;
- virtual void glGetShaderInfoLog_(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) override;
+ virtual void glGetProgramiv_(GLuint program, GLenum pname, GLint* params) override;
+ virtual void glGetProgramInfoLog_(GLuint program, GLsizei bufSize, GLsizei* length,
+ GLchar* infoLog) override;
+ virtual void glGetShaderiv_(GLuint shader, GLenum pname, GLint* params) override;
+ virtual void glGetShaderInfoLog_(GLuint shader, GLsizei bufSize, GLsizei* length,
+ GLchar* infoLog) override;
virtual void glEnable_(GLenum cap) override;
virtual void glDisable_(GLenum cap) override;
virtual GLboolean glIsEnabled_(GLenum cap) override;
- virtual void glGetIntegerv_(GLenum pname, GLint *data) override;
+ virtual void glGetIntegerv_(GLenum pname, GLint* data) override;
virtual const GLubyte* glGetString_(GLenum name) override;
virtual GLenum glCheckFramebufferStatus_(GLenum target) override;
virtual void glActiveTexture_(GLenum texture) override {}
virtual void glAttachShader_(GLuint program, GLuint shader) override {}
- virtual void glBindAttribLocation_(GLuint program, GLuint index, const GLchar *name) override {}
+ virtual void glBindAttribLocation_(GLuint program, GLuint index, const GLchar* name) override {}
virtual void glBindBuffer_(GLenum target, GLuint buffer) override {}
virtual void glBindFramebuffer_(GLenum target, GLuint framebuffer) override {}
virtual void glBindRenderbuffer_(GLenum target, GLuint renderbuffer) override {}
@@ -54,116 +56,147 @@ public:
virtual void glBlendEquation_(GLenum mode) override {}
virtual void glBlendEquationSeparate_(GLenum modeRGB, GLenum modeAlpha) override {}
virtual void glBlendFunc_(GLenum sfactor, GLenum dfactor) override {}
- virtual void glBlendFuncSeparate_(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) override {}
- virtual void glBufferData_(GLenum target, GLsizeiptr size, const void *data, GLenum usage) override {}
- virtual void glBufferSubData_(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) override {}
+ virtual void glBlendFuncSeparate_(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha,
+ GLenum dfactorAlpha) override {}
+ virtual void glBufferData_(GLenum target, GLsizeiptr size, const void* data,
+ GLenum usage) override {}
+ virtual void glBufferSubData_(GLenum target, GLintptr offset, GLsizeiptr size,
+ const void* data) override {}
virtual void glClear_(GLbitfield mask) override {}
virtual void glClearColor_(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) override {}
virtual void glClearDepthf_(GLfloat d) override {}
virtual void glClearStencil_(GLint s) override {}
- virtual void glColorMask_(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) override {}
+ virtual void glColorMask_(GLboolean red, GLboolean green, GLboolean blue,
+ GLboolean alpha) override {}
virtual void glCompileShader_(GLuint shader) override {}
- virtual void glCompressedTexImage2D_(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) override {}
- virtual void glCompressedTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) override {}
- virtual void glCopyTexImage2D_(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) override {}
- virtual void glCopyTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) override {}
+ virtual void glCompressedTexImage2D_(GLenum target, GLint level, GLenum internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const void* data) override {}
+ virtual void glCompressedTexSubImage2D_(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize,
+ const void* data) override {}
+ virtual void glCopyTexImage2D_(GLenum target, GLint level, GLenum internalformat, GLint x,
+ GLint y, GLsizei width, GLsizei height, GLint border) override {}
+ virtual void glCopyTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height) override {}
virtual void glCullFace_(GLenum mode) override {}
- virtual void glDeleteBuffers_(GLsizei n, const GLuint *buffers) override {}
- virtual void glDeleteFramebuffers_(GLsizei n, const GLuint *framebuffers) override {}
+ virtual void glDeleteBuffers_(GLsizei n, const GLuint* buffers) override {}
+ virtual void glDeleteFramebuffers_(GLsizei n, const GLuint* framebuffers) override {}
virtual void glDeleteProgram_(GLuint program) override {}
- virtual void glDeleteRenderbuffers_(GLsizei n, const GLuint *renderbuffers) override {}
+ virtual void glDeleteRenderbuffers_(GLsizei n, const GLuint* renderbuffers) override {}
virtual void glDeleteShader_(GLuint shader) override {}
- virtual void glDeleteTextures_(GLsizei n, const GLuint *textures) override {}
+ virtual void glDeleteTextures_(GLsizei n, const GLuint* textures) override {}
virtual void glDepthFunc_(GLenum func) override {}
virtual void glDepthMask_(GLboolean flag) override {}
virtual void glDepthRangef_(GLfloat n, GLfloat f) override {}
virtual void glDetachShader_(GLuint program, GLuint shader) override {}
virtual void glDisableVertexAttribArray_(GLuint index) override {}
virtual void glDrawArrays_(GLenum mode, GLint first, GLsizei count) override {}
- virtual void glDrawElements_(GLenum mode, GLsizei count, GLenum type, const void *indices) override {}
+ virtual void glDrawElements_(GLenum mode, GLsizei count, GLenum type,
+ const void* indices) override {}
virtual void glEnableVertexAttribArray_(GLuint index) override {}
virtual void glFinish_(void) override {}
virtual void glFlush_(void) override {}
- virtual void glFramebufferRenderbuffer_(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) override {}
- virtual void glFramebufferTexture2D_(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) override {}
+ virtual void glFramebufferRenderbuffer_(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer) override {}
+ virtual void glFramebufferTexture2D_(GLenum target, GLenum attachment, GLenum textarget,
+ GLuint texture, GLint level) override {}
virtual void glFrontFace_(GLenum mode) override {}
virtual void glGenerateMipmap_(GLenum target) override {}
- virtual GLint glGetAttribLocation_(GLuint program, const GLchar *name) override { return 1; }
+ virtual GLint glGetAttribLocation_(GLuint program, const GLchar* name) override { return 1; }
virtual GLenum glGetError_(void) override { return GL_NO_ERROR; }
- virtual GLint glGetUniformLocation_(GLuint program, const GLchar *name) override { return 2; }
+ virtual GLint glGetUniformLocation_(GLuint program, const GLchar* name) override { return 2; }
virtual void glHint_(GLenum target, GLenum mode) override {}
virtual void glLineWidth_(GLfloat width) override {}
virtual void glLinkProgram_(GLuint program) override {}
virtual void glPixelStorei_(GLenum pname, GLint param) override {}
virtual void glPolygonOffset_(GLfloat factor, GLfloat units) override {}
- virtual void glReadPixels_(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) override {}
+ virtual void glReadPixels_(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, void* pixels) override {}
virtual void glReleaseShaderCompiler_(void) override {}
- virtual void glRenderbufferStorage_(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) override {}
+ virtual void glRenderbufferStorage_(GLenum target, GLenum internalformat, GLsizei width,
+ GLsizei height) override {}
virtual void glSampleCoverage_(GLfloat value, GLboolean invert) override {}
virtual void glScissor_(GLint x, GLint y, GLsizei width, GLsizei height) override {}
- virtual void glShaderBinary_(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length) override {}
- virtual void glShaderSource_(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) override {}
+ virtual void glShaderBinary_(GLsizei count, const GLuint* shaders, GLenum binaryformat,
+ const void* binary, GLsizei length) override {}
+ virtual void glShaderSource_(GLuint shader, GLsizei count, const GLchar* const* string,
+ const GLint* length) override {}
virtual void glStencilFunc_(GLenum func, GLint ref, GLuint mask) override {}
- virtual void glStencilFuncSeparate_(GLenum face, GLenum func, GLint ref, GLuint mask) override {}
+ virtual void glStencilFuncSeparate_(GLenum face, GLenum func, GLint ref, GLuint mask) override {
+ }
virtual void glStencilMask_(GLuint mask) override {}
virtual void glStencilMaskSeparate_(GLenum face, GLuint mask) override {}
virtual void glStencilOp_(GLenum fail, GLenum zfail, GLenum zpass) override {}
- virtual void glStencilOpSeparate_(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) override {}
- virtual void glTexImage2D_(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) override {}
+ virtual void glStencilOpSeparate_(GLenum face, GLenum sfail, GLenum dpfail,
+ GLenum dppass) override {}
+ virtual void glTexImage2D_(GLenum target, GLint level, GLint internalformat, GLsizei width,
+ GLsizei height, GLint border, GLenum format, GLenum type,
+ const void* pixels) override {}
virtual void glTexParameterf_(GLenum target, GLenum pname, GLfloat param) override {}
- virtual void glTexParameterfv_(GLenum target, GLenum pname, const GLfloat *params) override {}
+ virtual void glTexParameterfv_(GLenum target, GLenum pname, const GLfloat* params) override {}
virtual void glTexParameteri_(GLenum target, GLenum pname, GLint param) override {}
- virtual void glTexParameteriv_(GLenum target, GLenum pname, const GLint *params) override {}
- virtual void glTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) override {}
+ virtual void glTexParameteriv_(GLenum target, GLenum pname, const GLint* params) override {}
+ virtual void glTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height, GLenum format, GLenum type,
+ const void* pixels) override {}
virtual void glUniform1f_(GLint location, GLfloat v0) override {}
- virtual void glUniform1fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform1fv_(GLint location, GLsizei count, const GLfloat* value) override {}
virtual void glUniform1i_(GLint location, GLint v0) override {}
- virtual void glUniform1iv_(GLint location, GLsizei count, const GLint *value) override {}
+ virtual void glUniform1iv_(GLint location, GLsizei count, const GLint* value) override {}
virtual void glUniform2f_(GLint location, GLfloat v0, GLfloat v1) override {}
- virtual void glUniform2fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform2fv_(GLint location, GLsizei count, const GLfloat* value) override {}
virtual void glUniform2i_(GLint location, GLint v0, GLint v1) override {}
- virtual void glUniform2iv_(GLint location, GLsizei count, const GLint *value) override {}
+ virtual void glUniform2iv_(GLint location, GLsizei count, const GLint* value) override {}
virtual void glUniform3f_(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) override {}
- virtual void glUniform3fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform3fv_(GLint location, GLsizei count, const GLfloat* value) override {}
virtual void glUniform3i_(GLint location, GLint v0, GLint v1, GLint v2) override {}
- virtual void glUniform3iv_(GLint location, GLsizei count, const GLint *value) override {}
- virtual void glUniform4f_(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) override {}
- virtual void glUniform4fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform3iv_(GLint location, GLsizei count, const GLint* value) override {}
+ virtual void glUniform4f_(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
+ GLfloat v3) override {}
+ virtual void glUniform4fv_(GLint location, GLsizei count, const GLfloat* value) override {}
virtual void glUniform4i_(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) override {}
- virtual void glUniform4iv_(GLint location, GLsizei count, const GLint *value) override {}
- virtual void glUniformMatrix2fv_(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override {}
- virtual void glUniformMatrix3fv_(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override {}
- virtual void glUniformMatrix4fv_(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override {}
+ virtual void glUniform4iv_(GLint location, GLsizei count, const GLint* value) override {}
+ virtual void glUniformMatrix2fv_(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat* value) override {}
+ virtual void glUniformMatrix3fv_(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat* value) override {}
+ virtual void glUniformMatrix4fv_(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat* value) override {}
virtual void glUseProgram_(GLuint program) override {}
virtual void glValidateProgram_(GLuint program) override {}
virtual void glVertexAttrib1f_(GLuint index, GLfloat x) override {}
- virtual void glVertexAttrib1fv_(GLuint index, const GLfloat *v) override {}
+ virtual void glVertexAttrib1fv_(GLuint index, const GLfloat* v) override {}
virtual void glVertexAttrib2f_(GLuint index, GLfloat x, GLfloat y) override {}
- virtual void glVertexAttrib2fv_(GLuint index, const GLfloat *v) override {}
+ virtual void glVertexAttrib2fv_(GLuint index, const GLfloat* v) override {}
virtual void glVertexAttrib3f_(GLuint index, GLfloat x, GLfloat y, GLfloat z) override {}
- virtual void glVertexAttrib3fv_(GLuint index, const GLfloat *v) override {}
- virtual void glVertexAttrib4f_(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) override {}
- virtual void glVertexAttrib4fv_(GLuint index, const GLfloat *v) override {}
- virtual void glVertexAttribPointer_(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) override {}
+ virtual void glVertexAttrib3fv_(GLuint index, const GLfloat* v) override {}
+ virtual void glVertexAttrib4f_(GLuint index, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat w) override {}
+ virtual void glVertexAttrib4fv_(GLuint index, const GLfloat* v) override {}
+ virtual void glVertexAttribPointer_(GLuint index, GLint size, GLenum type, GLboolean normalized,
+ GLsizei stride, const void* pointer) override {}
virtual void glViewport_(GLint x, GLint y, GLsizei width, GLsizei height) override {}
// gles2 ext
- virtual void glInsertEventMarkerEXT_(GLsizei length, const GLchar *marker) override {}
- virtual void glPushGroupMarkerEXT_(GLsizei length, const GLchar *marker) override {}
+ virtual void glInsertEventMarkerEXT_(GLsizei length, const GLchar* marker) override {}
+ virtual void glPushGroupMarkerEXT_(GLsizei length, const GLchar* marker) override {}
virtual void glPopGroupMarkerEXT_(void) override {}
- virtual void glDiscardFramebufferEXT_(GLenum target, GLsizei numAttachments, const GLenum *attachments) override {}
+ virtual void glDiscardFramebufferEXT_(GLenum target, GLsizei numAttachments,
+ const GLenum* attachments) override {}
virtual void glEGLImageTargetTexture2DOES_(GLenum target, GLeglImageOES image) override {}
// GLES3
- virtual void* glMapBufferRange_(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) override {
+ virtual void* glMapBufferRange_(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access) override {
return 0;
}
- virtual GLboolean glUnmapBuffer_(GLenum target) override {
- return GL_FALSE;
- }
+ virtual GLboolean glUnmapBuffer_(GLenum target) override { return GL_FALSE; }
};
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/ScopedReplaceDriver.h b/libs/hwui/debug/ScopedReplaceDriver.h
index 342c9d223727..110196fb2a01 100644
--- a/libs/hwui/debug/ScopedReplaceDriver.h
+++ b/libs/hwui/debug/ScopedReplaceDriver.h
@@ -33,14 +33,13 @@ public:
Driver& get() { return *mCurrentDriver; }
- ~ScopedReplaceDriver() {
- GlesDriver::replace(std::move(mOldDriver));
- }
+ ~ScopedReplaceDriver() { GlesDriver::replace(std::move(mOldDriver)); }
+
private:
std::unique_ptr<GlesDriver> mOldDriver;
Driver* mCurrentDriver;
};
-} // namespace debug
-} // namespace uirenderer
-} // namespace android
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/gles_decls.in b/libs/hwui/debug/gles_decls.in
index 16574a7fb074..3900959c29de 100644
--- a/libs/hwui/debug/gles_decls.in
+++ b/libs/hwui/debug/gles_decls.in
@@ -387,7 +387,6 @@ GL_ENTRY(GLboolean, glIsEnablediOES, GLenum target, GLuint index)
GL_ENTRY(void, glDrawElementsBaseVertexOES, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
GL_ENTRY(void, glDrawRangeElementsBaseVertexOES, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
GL_ENTRY(void, glDrawElementsInstancedBaseVertexOES, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
-GL_ENTRY(void, glMultiDrawElementsBaseVertexOES, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex)
GL_ENTRY(void, glFramebufferTextureOES, GLenum target, GLenum attachment, GLuint texture, GLint level)
GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
@@ -541,4 +540,4 @@ GL_ENTRY(void, glTexStorage3DEXT, GLenum target, GLsizei levels, GLenum internal
GL_ENTRY(void, glTextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
GL_ENTRY(void, glTextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
GL_ENTRY(void, glTextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
-GL_ENTRY(void, glTextureViewEXT, GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) \ No newline at end of file
+GL_ENTRY(void, glTextureViewEXT, GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
diff --git a/libs/hwui/debug/gles_redefine.h b/libs/hwui/debug/gles_redefine.h
index 201f0a945209..49b506918372 100644
--- a/libs/hwui/debug/gles_redefine.h
+++ b/libs/hwui/debug/gles_redefine.h
@@ -212,7 +212,8 @@
#define glDrawElementsInstancedANGLE wrap_glDrawElementsInstancedANGLE
#define glDrawElementsInstancedBaseInstanceEXT wrap_glDrawElementsInstancedBaseInstanceEXT
#define glDrawElementsInstancedBaseVertex wrap_glDrawElementsInstancedBaseVertex
-#define glDrawElementsInstancedBaseVertexBaseInstanceEXT wrap_glDrawElementsInstancedBaseVertexBaseInstanceEXT
+#define glDrawElementsInstancedBaseVertexBaseInstanceEXT \
+ wrap_glDrawElementsInstancedBaseVertexBaseInstanceEXT
#define glDrawElementsInstancedBaseVertexEXT wrap_glDrawElementsInstancedBaseVertexEXT
#define glDrawElementsInstancedBaseVertexOES wrap_glDrawElementsInstancedBaseVertexOES
#define glDrawElementsInstancedEXT wrap_glDrawElementsInstancedEXT
diff --git a/libs/hwui/debug/gles_stubs.in b/libs/hwui/debug/gles_stubs.in
index 4064a391a71d..7cba0c115814 100644
--- a/libs/hwui/debug/gles_stubs.in
+++ b/libs/hwui/debug/gles_stubs.in
@@ -1165,9 +1165,6 @@ void API_ENTRY(glDrawRangeElementsBaseVertexOES)(GLenum mode, GLuint start, GLui
void API_ENTRY(glDrawElementsInstancedBaseVertexOES)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) {
CALL_GL_API(glDrawElementsInstancedBaseVertexOES, mode, count, type, indices, instancecount, basevertex);
}
-void API_ENTRY(glMultiDrawElementsBaseVertexOES)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex) {
- CALL_GL_API(glMultiDrawElementsBaseVertexOES, mode, count, type, indices, primcount, basevertex);
-}
void API_ENTRY(glFramebufferTextureOES)(GLenum target, GLenum attachment, GLuint texture, GLint level) {
CALL_GL_API(glFramebufferTextureOES, target, attachment, texture, level);
}
@@ -1629,4 +1626,4 @@ void API_ENTRY(glTextureStorage3DEXT)(GLuint texture, GLenum target, GLsizei lev
}
void API_ENTRY(glTextureViewEXT)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) {
CALL_GL_API(glTextureViewEXT, texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
-} \ No newline at end of file
+}
diff --git a/libs/hwui/debug/nullegl.cpp b/libs/hwui/debug/nullegl.cpp
index 2ae71df5c22c..ca47f8fd22ef 100644
--- a/libs/hwui/debug/nullegl.cpp
+++ b/libs/hwui/debug/nullegl.cpp
@@ -21,8 +21,8 @@
#include <stdlib.h>
#include <string.h>
-static EGLDisplay gDisplay = (EGLDisplay) 1;
-static EGLSyncKHR gFence = (EGLSyncKHR) 1;
+static EGLDisplay gDisplay = (EGLDisplay)1;
+static EGLSyncKHR gFence = (EGLSyncKHR)1;
typedef struct {
EGLSurface surface;
@@ -43,8 +43,8 @@ static void makeThreadState() {
ThreadState* getThreadState() {
ThreadState* ptr;
pthread_once(&ThreadStateSetupOnce, makeThreadState);
- if ((ptr = (ThreadState*) pthread_getspecific(ThreadStateKey)) == NULL) {
- ptr = (ThreadState*) calloc(1, sizeof(ThreadState));
+ if ((ptr = (ThreadState*)pthread_getspecific(ThreadStateKey)) == NULL) {
+ ptr = (ThreadState*)calloc(1, sizeof(ThreadState));
ptr->context = EGL_NO_CONTEXT;
ptr->surface = EGL_NO_SURFACE;
pthread_setspecific(ThreadStateKey, ptr);
@@ -60,7 +60,7 @@ EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) {
return gDisplay;
}
-EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) {
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) {
return EGL_TRUE;
}
@@ -68,30 +68,27 @@ EGLBoolean eglTerminate(EGLDisplay dpy) {
return EGL_TRUE;
}
-const char * eglQueryString(EGLDisplay dpy, EGLint name) {
+const char* eglQueryString(EGLDisplay dpy, EGLint name) {
if (name == EGL_EXTENSIONS) {
return "EGL_KHR_swap_buffers_with_damage";
}
return "";
}
-EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
- EGLConfig *configs, EGLint config_size,
- EGLint *num_config) {
+EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs,
+ EGLint config_size, EGLint* num_config) {
memset(configs, 9, sizeof(EGLConfig) * config_size);
*num_config = config_size;
return EGL_TRUE;
}
-EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
- EGLNativeWindowType win,
- const EGLint *attrib_list) {
- return (EGLSurface) malloc(sizeof(void*));
+EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
+ const EGLint* attrib_list) {
+ return (EGLSurface)malloc(sizeof(void*));
}
-EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
- const EGLint *attrib_list) {
- return (EGLSurface) malloc(sizeof(void*));
+EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) {
+ return (EGLSurface)malloc(sizeof(void*));
}
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) {
@@ -99,8 +96,7 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) {
return EGL_TRUE;
}
-EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
- EGLint attribute, EGLint *value) {
+EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value) {
*value = 1000;
return EGL_TRUE;
}
@@ -109,8 +105,7 @@ EGLBoolean eglReleaseThread(void) {
return EGL_TRUE;
}
-EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
- EGLint attribute, EGLint value) {
+EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) {
return EGL_TRUE;
}
@@ -118,18 +113,16 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) {
return EGL_TRUE;
}
-EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
- EGLContext share_context,
- const EGLint *attrib_list) {
- return (EGLContext) malloc(sizeof(void*));
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context,
+ const EGLint* attrib_list) {
+ return (EGLContext)malloc(sizeof(void*));
}
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) {
free(ctx);
return EGL_TRUE;
}
-EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
- EGLSurface read, EGLContext ctx) {
+EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
ThreadState* state = getThreadState();
state->surface = draw;
state->context = ctx;
@@ -152,15 +145,17 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
return EGL_TRUE;
}
-EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint rectCount) {
+EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, EGLint* rects,
+ EGLint rectCount) {
return EGL_TRUE;
}
-EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) {
- return (EGLImageKHR) malloc(sizeof(EGLImageKHR));
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint* attrib_list) {
+ return (EGLImageKHR)malloc(sizeof(EGLImageKHR));
}
-EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) {
+EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) {
return gFence;
}
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 73beba9297c4..5dd8bb8119e9 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -16,12 +16,12 @@
#include <SkGlyph.h>
-#include "CacheTexture.h"
-#include "FontUtil.h"
#include "../Caches.h"
#include "../Debug.h"
#include "../Extensions.h"
#include "../PixelBuffer.h"
+#include "CacheTexture.h"
+#include "FontUtil.h"
namespace android {
namespace uirenderer {
@@ -37,9 +37,8 @@ namespace uirenderer {
*/
CacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock* newBlock) {
#if DEBUG_FONT_RENDERER
- ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d",
- newBlock, newBlock->mX, newBlock->mY,
- newBlock->mWidth, newBlock->mHeight);
+ ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d", newBlock, newBlock->mX,
+ newBlock->mY, newBlock->mWidth, newBlock->mHeight);
#endif
CacheBlock* currBlock = head;
@@ -81,9 +80,8 @@ CacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock* newBlock) {
CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove) {
#if DEBUG_FONT_RENDERER
- ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d",
- blockToRemove, blockToRemove->mX, blockToRemove->mY,
- blockToRemove->mWidth, blockToRemove->mHeight);
+ ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d", blockToRemove, blockToRemove->mX,
+ blockToRemove->mY, blockToRemove->mWidth, blockToRemove->mHeight);
#endif
CacheBlock* newHead = head;
@@ -93,7 +91,7 @@ CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove)
if (prevBlock) {
// If this doesn't hold, we have a use-after-free below.
LOG_ALWAYS_FATAL_IF(head == blockToRemove,
- "removeBlock: head should not have a previous block");
+ "removeBlock: head should not have a previous block");
prevBlock->mNext = nextBlock;
} else {
newHead = nextBlock;
@@ -121,8 +119,9 @@ CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint3
, mCaches(Caches::getInstance()) {
mTexture.blend = true;
- mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
- getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE);
+ mCacheBlocks =
+ new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
+ getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE);
// OpenGL ES 3.0+ lets us specify the row length for unpack operations such
// as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture.
@@ -150,8 +149,9 @@ void CacheTexture::reset() {
void CacheTexture::init() {
// reset, then create a new remainder space to start again
reset();
- mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
- getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE);
+ mCacheBlocks =
+ new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
+ getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE);
}
void CacheTexture::releaseMesh() {
@@ -233,7 +233,7 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
if (mFormat != GL_ALPHA) {
#if DEBUG_FONT_RENDERER
ALOGD("fitBitmap: texture format %x is inappropriate for monochromatic glyphs",
- mFormat);
+ mFormat);
#endif
return false;
}
@@ -272,8 +272,8 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
// it's the remainder space (mY == 0) or there's only enough height for this one glyph
// or it's within ROUNDING_SIZE of the block width
if (roundedUpW <= cacheBlock->mWidth && glyphH <= cacheBlock->mHeight &&
- (cacheBlock->mY == TEXTURE_BORDER_SIZE ||
- (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) {
+ (cacheBlock->mY == TEXTURE_BORDER_SIZE ||
+ (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) {
if (cacheBlock->mHeight - glyphH < glyphH) {
// Only enough space for this glyph - don't bother rounding up the width
roundedUpW = glyphW;
@@ -292,12 +292,13 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
if (getHeight() - glyphH >= glyphH) {
// There's enough height left over to create a new CacheBlock
- CacheBlock* newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE,
- roundedUpW, getHeight() - glyphH - TEXTURE_BORDER_SIZE);
+ CacheBlock* newBlock =
+ new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE, roundedUpW,
+ getHeight() - glyphH - TEXTURE_BORDER_SIZE);
#if DEBUG_FONT_RENDERER
ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
- newBlock, newBlock->mX, newBlock->mY,
- newBlock->mWidth, newBlock->mHeight);
+ newBlock, newBlock->mX, newBlock->mY, newBlock->mWidth,
+ newBlock->mHeight);
#endif
mCacheBlocks = CacheBlock::insertBlock(mCacheBlocks, newBlock);
}
@@ -307,8 +308,8 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
cacheBlock->mHeight -= glyphH;
#if DEBUG_FONT_RENDERER
ALOGD("fitBitmap: Added to existing block: this, x, y, w, h = %p, %d, %d, %d, %d",
- cacheBlock, cacheBlock->mX, cacheBlock->mY,
- cacheBlock->mWidth, cacheBlock->mHeight);
+ cacheBlock, cacheBlock->mX, cacheBlock->mY, cacheBlock->mWidth,
+ cacheBlock->mHeight);
#endif
}
@@ -319,7 +320,7 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
mDirty = true;
const Rect r(*retOriginX - TEXTURE_BORDER_SIZE, *retOriginY - TEXTURE_BORDER_SIZE,
- *retOriginX + glyphW, *retOriginY + glyphH);
+ *retOriginX + glyphW, *retOriginY + glyphH);
mDirtyRect.unionWith(r);
mNumGlyphs++;
@@ -350,5 +351,5 @@ uint32_t CacheTexture::calculateFreeMemory() const {
return free;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h
index 6750a8ae11cf..654378eeb47e 100644
--- a/libs/hwui/font/CacheTexture.h
+++ b/libs/hwui/font/CacheTexture.h
@@ -26,7 +26,6 @@
#include <SkGlyph.h>
#include <utils/Log.h>
-
namespace android {
namespace uirenderer {
@@ -53,9 +52,8 @@ struct CacheBlock {
CacheBlock* mNext;
CacheBlock* mPrev;
- CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height):
- mX(x), mY(y), mWidth(width), mHeight(height), mNext(nullptr), mPrev(nullptr) {
- }
+ CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
+ : mX(x), mY(y), mWidth(width), mHeight(height), mNext(nullptr), mPrev(nullptr) {}
static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock);
static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove);
@@ -63,9 +61,8 @@ struct CacheBlock {
void output() {
CacheBlock* currBlock = this;
while (currBlock) {
- ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
- currBlock, currBlock->mX, currBlock->mY,
- currBlock->mWidth, currBlock->mHeight);
+ ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d", currBlock, currBlock->mX,
+ currBlock->mY, currBlock->mWidth, currBlock->mHeight);
currBlock = currBlock->mNext;
}
}
@@ -91,29 +88,19 @@ public:
bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
- inline uint16_t getWidth() const {
- return mWidth;
- }
+ inline uint16_t getWidth() const { return mWidth; }
- inline uint16_t getHeight() const {
- return mHeight;
- }
+ inline uint16_t getHeight() const { return mHeight; }
- inline GLenum getFormat() const {
- return mFormat;
- }
+ inline GLenum getFormat() const { return mFormat; }
inline uint32_t getOffset(uint16_t x, uint16_t y) const {
return (y * getWidth() + x) * PixelBuffer::formatSize(mFormat);
}
- inline const Rect* getDirtyRect() const {
- return &mDirtyRect;
- }
+ inline const Rect* getDirtyRect() const { return &mDirtyRect; }
- inline PixelBuffer* getPixelBuffer() const {
- return mPixelBuffer;
- }
+ inline PixelBuffer* getPixelBuffer() const { return mPixelBuffer; }
Texture& getTexture() {
allocatePixelBuffer();
@@ -125,43 +112,28 @@ public:
return mTexture.id();
}
- inline bool isDirty() const {
- return mDirty;
- }
+ inline bool isDirty() const { return mDirty; }
- inline bool getLinearFiltering() const {
- return mLinearFiltering;
- }
+ inline bool getLinearFiltering() const { return mLinearFiltering; }
/**
* This method assumes that the proper texture unit is active.
*/
void setLinearFiltering(bool linearFiltering);
- inline uint16_t getGlyphCount() const {
- return mNumGlyphs;
- }
+ inline uint16_t getGlyphCount() const { return mNumGlyphs; }
- TextureVertex* mesh() const {
- return mMesh;
- }
+ TextureVertex* mesh() const { return mMesh; }
- uint32_t meshElementCount() const {
- return mCurrentQuad * 6;
- }
+ uint32_t meshElementCount() const { return mCurrentQuad * 6; }
- uint16_t* indices() const {
- return (uint16_t*) nullptr;
- }
+ uint16_t* indices() const { return (uint16_t*)nullptr; }
- void resetMesh() {
- mCurrentQuad = 0;
- }
+ void resetMesh() { mCurrentQuad = 0; }
- inline void addQuad(float x1, float y1, float u1, float v1,
- float x2, float y2, float u2, float v2,
- float x3, float y3, float u3, float v3,
- float x4, float y4, float u4, float v4) {
+ inline void addQuad(float x1, float y1, float u1, float v1, float x2, float y2, float u2,
+ float v2, float x3, float y3, float u3, float v3, float x4, float y4,
+ float u4, float v4) {
TextureVertex* mesh = mMesh + mCurrentQuad * 4;
TextureVertex::set(mesh++, x2, y2, u2, v2);
TextureVertex::set(mesh++, x3, y3, u3, v3);
@@ -170,13 +142,9 @@ public:
mCurrentQuad++;
}
- bool canDraw() const {
- return mCurrentQuad > 0;
- }
+ bool canDraw() const { return mCurrentQuad > 0; }
- bool endOfMesh() const {
- return mCurrentQuad == mMaxQuadCount;
- }
+ bool endOfMesh() const { return mCurrentQuad == mMaxQuadCount; }
uint32_t calculateFreeMemory() const;
@@ -199,7 +167,7 @@ private:
Rect mDirtyRect;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_CACHE_TEXTURE_H
+#endif // ANDROID_HWUI_CACHE_TEXTURE_H
diff --git a/libs/hwui/font/CachedGlyphInfo.h b/libs/hwui/font/CachedGlyphInfo.h
index 073d59bdea3f..93bb823db512 100644
--- a/libs/hwui/font/CachedGlyphInfo.h
+++ b/libs/hwui/font/CachedGlyphInfo.h
@@ -50,7 +50,7 @@ struct CachedGlyphInfo {
CacheTexture* mCacheTexture;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_CACHED_GLYPH_INFO_H
+#endif // ANDROID_HWUI_CACHED_GLYPH_INFO_H
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 24d497cb1860..41a24a809e89 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -19,17 +19,17 @@
#include <utils/JenkinsHash.h>
#include <utils/Trace.h>
-#include <SkSurfaceProps.h>
#include <SkGlyph.h>
#include <SkGlyphCache.h>
+#include <SkSurfaceProps.h>
#include <SkUtils.h>
-#include "FontUtil.h"
-#include "Font.h"
#include "../Debug.h"
#include "../FontRenderer.h"
#include "../PixelBuffer.h"
#include "../Properties.h"
+#include "Font.h"
+#include "FontUtil.h"
namespace android {
namespace uirenderer {
@@ -38,8 +38,8 @@ namespace uirenderer {
// Font
///////////////////////////////////////////////////////////////////////////////
-Font::Font(FontRenderer* state, const Font::FontDescription& desc) :
- mState(state), mDescription(desc) { }
+Font::Font(FontRenderer* state, const Font::FontDescription& desc)
+ : mState(state), mDescription(desc) {}
Font::FontDescription::FontDescription(const SkPaint* paint, const SkMatrix& rasterMatrix)
: mLookupTransform(rasterMatrix) {
@@ -82,7 +82,7 @@ hash_t Font::FontDescription::hash() const {
}
int Font::FontDescription::compare(const Font::FontDescription& lhs,
- const Font::FontDescription& rhs) {
+ const Font::FontDescription& rhs) {
int deltaInt = int(lhs.mFontId) - int(rhs.mFontId);
if (deltaInt != 0) return deltaInt;
@@ -110,15 +110,15 @@ int Font::FontDescription::compare(const Font::FontDescription& lhs,
deltaInt = int(lhs.mHinting) - int(rhs.mHinting);
if (deltaInt != 0) return deltaInt;
- if (lhs.mLookupTransform[SkMatrix::kMScaleX] <
- rhs.mLookupTransform[SkMatrix::kMScaleX]) return -1;
- if (lhs.mLookupTransform[SkMatrix::kMScaleX] >
- rhs.mLookupTransform[SkMatrix::kMScaleX]) return +1;
+ if (lhs.mLookupTransform[SkMatrix::kMScaleX] < rhs.mLookupTransform[SkMatrix::kMScaleX])
+ return -1;
+ if (lhs.mLookupTransform[SkMatrix::kMScaleX] > rhs.mLookupTransform[SkMatrix::kMScaleX])
+ return +1;
- if (lhs.mLookupTransform[SkMatrix::kMScaleY] <
- rhs.mLookupTransform[SkMatrix::kMScaleY]) return -1;
- if (lhs.mLookupTransform[SkMatrix::kMScaleY] >
- rhs.mLookupTransform[SkMatrix::kMScaleY]) return +1;
+ if (lhs.mLookupTransform[SkMatrix::kMScaleY] < rhs.mLookupTransform[SkMatrix::kMScaleY])
+ return -1;
+ if (lhs.mLookupTransform[SkMatrix::kMScaleY] > rhs.mLookupTransform[SkMatrix::kMScaleY])
+ return +1;
return 0;
}
@@ -132,10 +132,10 @@ void Font::invalidateTextureCache(CacheTexture* cacheTexture) {
}
}
-void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
- uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
- int width = (int) glyph->mBitmapWidth;
- int height = (int) glyph->mBitmapHeight;
+void Font::measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap,
+ uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
+ int width = (int)glyph->mBitmapWidth;
+ int height = (int)glyph->mBitmapHeight;
int nPenX = x + glyph->mBitmapLeft;
int nPenY = y + glyph->mBitmapTop;
@@ -154,10 +154,10 @@ void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
}
}
-void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
- uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
- float width = (float) glyph->mBitmapWidth;
- float height = (float) glyph->mBitmapHeight;
+void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW,
+ uint32_t bitmapH, Rect* bounds, const float* pos) {
+ float width = (float)glyph->mBitmapWidth;
+ float height = (float)glyph->mBitmapHeight;
float nPenX = x + glyph->mBitmapLeft;
float nPenY = y + glyph->mBitmapTop + height;
@@ -167,16 +167,16 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
float v1 = glyph->mBitmapMinV;
float v2 = glyph->mBitmapMaxV;
- mState->appendMeshQuad(nPenX, nPenY, u1, v2,
- nPenX + width, nPenY, u2, v2,
- nPenX + width, nPenY - height, u2, v1,
- nPenX, nPenY - height, u1, v1, glyph->mCacheTexture);
+ mState->appendMeshQuad(nPenX, nPenY, u1, v2, nPenX + width, nPenY, u2, v2, nPenX + width,
+ nPenY - height, u2, v1, nPenX, nPenY - height, u1, v1,
+ glyph->mCacheTexture);
}
-void Font::drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y,
- uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
- float width = (float) glyph->mBitmapWidth;
- float height = (float) glyph->mBitmapHeight;
+void Font::drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap,
+ uint32_t bitmapW, uint32_t bitmapH, Rect* bounds,
+ const float* pos) {
+ float width = (float)glyph->mBitmapWidth;
+ float height = (float)glyph->mBitmapHeight;
SkPoint p[4];
p[0].iset(glyph->mBitmapLeft, glyph->mBitmapTop + height);
@@ -196,15 +196,14 @@ void Font::drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y,
float v1 = glyph->mBitmapMinV;
float v2 = glyph->mBitmapMaxV;
- mState->appendRotatedMeshQuad(
- p[0].x(), p[0].y(), u1, v2,
- p[1].x(), p[1].y(), u2, v2,
- p[2].x(), p[2].y(), u2, v1,
- p[3].x(), p[3].y(), u1, v1, glyph->mCacheTexture);
+ mState->appendRotatedMeshQuad(p[0].x(), p[0].y(), u1, v2, p[1].x(), p[1].y(), u2, v2, p[2].x(),
+ p[2].y(), u2, v1, p[3].x(), p[3].y(), u1, v1,
+ glyph->mCacheTexture);
}
void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap,
- uint32_t bitmapWidth, uint32_t bitmapHeight, Rect* bounds, const float* pos) {
+ uint32_t bitmapWidth, uint32_t bitmapHeight, Rect* bounds,
+ const float* pos) {
int dstX = x + glyph->mBitmapLeft;
int dstY = y + glyph->mBitmapTop;
@@ -221,12 +220,11 @@ void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t*
const uint8_t* cacheBuffer = pixelBuffer->map();
for (uint32_t cacheY = startY, bitmapY = dstY * bitmapWidth; cacheY < endY;
- cacheY += srcStride, bitmapY += bitmapWidth) {
-
+ cacheY += srcStride, bitmapY += bitmapWidth) {
for (uint32_t i = 0; i < glyph->mBitmapWidth; ++i) {
uint8_t* dst = &(bitmap[bitmapY + dstX + i]);
- const uint8_t& src = cacheBuffer[
- cacheY + (glyph->mStartX + i)*formatSize + alpha_channel_offset];
+ const uint8_t& src =
+ cacheBuffer[cacheY + (glyph->mStartX + i) * formatSize + alpha_channel_offset];
// Add alpha values to a max of 255, full opacity. This is done to handle
// fonts/strings where glyphs overlap.
*dst = std::min(*dst + src, 255);
@@ -235,7 +233,7 @@ void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t*
}
void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
- SkPathMeasure& measure, SkPoint* position, SkVector* tangent) {
+ SkPathMeasure& measure, SkPoint* position, SkVector* tangent) {
const float halfWidth = glyph->mBitmapWidth * 0.5f;
const float height = glyph->mBitmapHeight;
@@ -249,13 +247,13 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float
// Move along the tangent and offset by the normal
destination[0].set(-tangent->fX * halfWidth - tangent->fY * vOffset,
- -tangent->fY * halfWidth + tangent->fX * vOffset);
+ -tangent->fY * halfWidth + tangent->fX * vOffset);
destination[1].set(tangent->fX * halfWidth - tangent->fY * vOffset,
- tangent->fY * halfWidth + tangent->fX * vOffset);
+ tangent->fY * halfWidth + tangent->fX * vOffset);
destination[2].set(destination[1].fX + tangent->fY * height,
- destination[1].fY - tangent->fX * height);
+ destination[1].fY - tangent->fX * height);
destination[3].set(destination[0].fX + tangent->fY * height,
- destination[0].fY - tangent->fX * height);
+ destination[0].fY - tangent->fX * height);
const float u1 = glyph->mBitmapMinU;
const float u2 = glyph->mBitmapMaxU;
@@ -263,14 +261,10 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float
const float v2 = glyph->mBitmapMaxV;
mState->appendRotatedMeshQuad(
- position->x() + destination[0].x(),
- position->y() + destination[0].y(), u1, v2,
- position->x() + destination[1].x(),
- position->y() + destination[1].y(), u2, v2,
- position->x() + destination[2].x(),
- position->y() + destination[2].y(), u2, v1,
- position->x() + destination[3].x(),
- position->y() + destination[3].y(), u1, v1,
+ position->x() + destination[0].x(), position->y() + destination[0].y(), u1, v2,
+ position->x() + destination[1].x(), position->y() + destination[1].y(), u2, v2,
+ position->x() + destination[2].x(), position->y() + destination[2].y(), u2, v1,
+ position->x() + destination[3].x(), position->y() + destination[3].y(), u1, v1,
glyph->mCacheTexture);
}
@@ -280,7 +274,8 @@ CachedGlyphInfo* Font::getCachedGlyph(const SkPaint* paint, glyph_t textUnit, bo
// Is the glyph still in texture cache?
if (!cachedGlyph->mIsValid) {
SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
- SkAutoGlyphCacheNoGamma autoCache(*paint, &surfaceProps, &mDescription.mLookupTransform);
+ SkAutoGlyphCacheNoGamma autoCache(*paint, &surfaceProps,
+ &mDescription.mLookupTransform);
const SkGlyph& skiaGlyph = GET_METRICS(autoCache.getCache(), textUnit);
updateGlyphCache(paint, skiaGlyph, autoCache.getCache(), cachedGlyph, precaching);
}
@@ -291,14 +286,13 @@ CachedGlyphInfo* Font::getCachedGlyph(const SkPaint* paint, glyph_t textUnit, bo
return cachedGlyph;
}
-void Font::render(const SkPaint* paint, const glyph_t* glyphs,
- int numGlyphs, int x, int y, const float* positions) {
- render(paint, glyphs, numGlyphs, x, y, FRAMEBUFFER, nullptr,
- 0, 0, nullptr, positions);
+void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y,
+ const float* positions) {
+ render(paint, glyphs, numGlyphs, x, y, FRAMEBUFFER, nullptr, 0, 0, nullptr, positions);
}
-void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
- const SkPath* path, float hOffset, float vOffset) {
+void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, const SkPath* path,
+ float hOffset, float vOffset) {
if (numGlyphs == 0 || glyphs == nullptr) {
return;
}
@@ -345,8 +339,8 @@ void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
}
}
-void Font::measure(const SkPaint* paint, const glyph_t* glyphs,
- int numGlyphs, Rect *bounds, const float* positions) {
+void Font::measure(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, Rect* bounds,
+ const float* positions) {
if (bounds == nullptr) {
ALOGE("No return rectangle provided to measure text");
return;
@@ -374,21 +368,19 @@ void Font::precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs)
}
}
-void Font::render(const SkPaint* paint, const glyph_t* glyphs,
- int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
- uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* positions) {
+void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y,
+ RenderMode mode, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH,
+ Rect* bounds, const float* positions) {
if (numGlyphs == 0 || glyphs == nullptr) {
return;
}
- static RenderGlyph gRenderGlyph[] = {
- &android::uirenderer::Font::drawCachedGlyph,
- &android::uirenderer::Font::drawCachedGlyphTransformed,
- &android::uirenderer::Font::drawCachedGlyphBitmap,
- &android::uirenderer::Font::drawCachedGlyphBitmap,
- &android::uirenderer::Font::measureCachedGlyph,
- &android::uirenderer::Font::measureCachedGlyph
- };
+ static RenderGlyph gRenderGlyph[] = {&android::uirenderer::Font::drawCachedGlyph,
+ &android::uirenderer::Font::drawCachedGlyphTransformed,
+ &android::uirenderer::Font::drawCachedGlyphBitmap,
+ &android::uirenderer::Font::drawCachedGlyphBitmap,
+ &android::uirenderer::Font::measureCachedGlyph,
+ &android::uirenderer::Font::measureCachedGlyph};
RenderGlyph render = gRenderGlyph[(mode << 1) + !mIdentityTransform];
int glyphsCount = 0;
@@ -406,13 +398,12 @@ void Font::render(const SkPaint* paint, const glyph_t* glyphs,
// If it's still not valid, we couldn't cache it, so we shouldn't
// draw garbage; also skip empty glyphs (spaces)
if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) {
- int penX = x + (int) roundf(positions[(glyphsCount << 1)]);
- int penY = y + (int) roundf(positions[(glyphsCount << 1) + 1]);
+ int penX = x + (int)roundf(positions[(glyphsCount << 1)]);
+ int penY = y + (int)roundf(positions[(glyphsCount << 1) + 1]);
#ifdef BUGREPORT_FONT_CACHE_USAGE
mState->historyTracker().glyphRendered(cachedGlyph, penX, penY);
#endif
- (*this.*render)(cachedGlyph, penX, penY,
- bitmap, bitmapW, bitmapH, bounds, positions);
+ (*this.*render)(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH, bounds, positions);
} else {
#ifdef BUGREPORT_FONT_CACHE_USAGE
mState->historyTracker().glyphRendered(cachedGlyph, -1, -1);
@@ -424,7 +415,7 @@ void Font::render(const SkPaint* paint, const glyph_t* glyphs,
}
void Font::updateGlyphCache(const SkPaint* paint, const SkGlyph& skiaGlyph,
- SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching) {
+ SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching) {
glyph->mAdvanceX = skiaGlyph.fAdvanceX;
glyph->mAdvanceY = skiaGlyph.fAdvanceY;
glyph->mBitmapLeft = skiaGlyph.fLeft;
@@ -458,10 +449,10 @@ void Font::updateGlyphCache(const SkPaint* paint, const SkGlyph& skiaGlyph,
uint32_t cacheWidth = glyph->mCacheTexture->getWidth();
uint32_t cacheHeight = glyph->mCacheTexture->getHeight();
- glyph->mBitmapMinU = startX / (float) cacheWidth;
- glyph->mBitmapMinV = startY / (float) cacheHeight;
- glyph->mBitmapMaxU = endX / (float) cacheWidth;
- glyph->mBitmapMaxV = endY / (float) cacheHeight;
+ glyph->mBitmapMinU = startX / (float)cacheWidth;
+ glyph->mBitmapMinV = startY / (float)cacheHeight;
+ glyph->mBitmapMaxU = endX / (float)cacheWidth;
+ glyph->mBitmapMaxV = endY / (float)cacheHeight;
mState->setTextureDirty();
}
@@ -495,5 +486,5 @@ Font* Font::create(FontRenderer* state, const SkPaint* paint, const SkMatrix& ma
return font;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
index 504dabb5bcc0..85221bc069f1 100644
--- a/libs/hwui/font/Font.h
+++ b/libs/hwui/font/Font.h
@@ -21,14 +21,14 @@
#include <utils/KeyedVector.h>
-#include <SkScalar.h>
#include <SkPaint.h>
#include <SkPathMeasure.h>
+#include <SkScalar.h>
#include <SkTypeface.h>
-#include "FontUtil.h"
-#include "../Rect.h"
#include "../Matrix.h"
+#include "../Rect.h"
+#include "FontUtil.h"
class SkGlyphCache;
@@ -49,9 +49,7 @@ class FontRenderer;
*/
class Font {
public:
- enum Style {
- kFakeBold = 1
- };
+ enum Style { kFakeBold = 1 };
struct FontDescription {
FontDescription(const SkPaint* paint, const SkMatrix& matrix);
@@ -60,13 +58,9 @@ public:
hash_t hash() const;
- bool operator==(const FontDescription& other) const {
- return compare(*this, other) == 0;
- }
+ bool operator==(const FontDescription& other) const { return compare(*this, other) == 0; }
- bool operator!=(const FontDescription& other) const {
- return compare(*this, other) != 0;
- }
+ bool operator!=(const FontDescription& other) const { return compare(*this, other) != 0; }
SkFontID mFontId;
float mFontSize;
@@ -83,15 +77,13 @@ public:
~Font();
- void render(const SkPaint* paint, const glyph_t* glyphs,
- int numGlyphs, int x, int y, const float* positions);
+ void render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y,
+ const float* positions);
- void render(const SkPaint* paint, const glyph_t* glyphs,
- int numGlyphs, const SkPath* path, float hOffset, float vOffset);
+ void render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, const SkPath* path,
+ float hOffset, float vOffset);
- const Font::FontDescription& getDescription() const {
- return mDescription;
- }
+ const Font::FontDescription& getDescription() const { return mDescription; }
/**
* Creates a new font associated with the specified font state.
@@ -103,8 +95,8 @@ private:
Font(FontRenderer* state, const Font::FontDescription& desc);
- typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
- uint32_t, uint32_t, Rect*, const float*);
+ typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, uint32_t, uint32_t,
+ Rect*, const float*);
enum RenderMode {
FRAMEBUFFER,
@@ -114,36 +106,33 @@ private:
void precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs);
- void render(const SkPaint* paint, const glyph_t* glyphs,
- int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
- uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
+ void render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y,
+ RenderMode mode, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds,
+ const float* positions);
- void measure(const SkPaint* paint, const glyph_t* glyphs,
- int numGlyphs, Rect *bounds, const float* positions);
+ void measure(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, Rect* bounds,
+ const float* positions);
void invalidateTextureCache(CacheTexture* cacheTexture = nullptr);
CachedGlyphInfo* cacheGlyph(const SkPaint* paint, glyph_t glyph, bool precaching);
void updateGlyphCache(const SkPaint* paint, const SkGlyph& skiaGlyph,
- SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching);
-
- void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
- Rect* bounds, const float* pos);
- void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
- Rect* bounds, const float* pos);
- void drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
- Rect* bounds, const float* pos);
- void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
- Rect* bounds, const float* pos);
+ SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching);
+
+ void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW,
+ uint32_t bitmapH, Rect* bounds, const float* pos);
+ void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW,
+ uint32_t bitmapH, Rect* bounds, const float* pos);
+ void drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap,
+ uint32_t bitmapW, uint32_t bitmapH, Rect* bounds,
+ const float* pos);
+ void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap,
+ uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos);
void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
- SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
+ SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
CachedGlyphInfo* getCachedGlyph(const SkPaint* paint, glyph_t textUnit,
- bool precaching = false);
+ bool precaching = false);
FontRenderer* mState;
FontDescription mDescription;
@@ -154,8 +143,7 @@ private:
bool mIdentityTransform;
};
-inline int strictly_order_type(const Font::FontDescription& lhs,
- const Font::FontDescription& rhs) {
+inline int strictly_order_type(const Font::FontDescription& lhs, const Font::FontDescription& rhs) {
return Font::FontDescription::compare(lhs, rhs) < 0;
}
@@ -167,7 +155,7 @@ inline hash_t hash_type(const Font::FontDescription& entry) {
return entry.hash();
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_FONT_H
+#endif // ANDROID_HWUI_FONT_H
diff --git a/libs/hwui/font/FontCacheHistoryTracker.cpp b/libs/hwui/font/FontCacheHistoryTracker.cpp
index a2bfb27535e5..5b61c494524a 100644
--- a/libs/hwui/font/FontCacheHistoryTracker.cpp
+++ b/libs/hwui/font/FontCacheHistoryTracker.cpp
@@ -16,15 +16,15 @@
#include "FontCacheHistoryTracker.h"
-#include "CachedGlyphInfo.h"
#include "CacheTexture.h"
+#include "CachedGlyphInfo.h"
namespace android {
namespace uirenderer {
void FontCacheHistoryTracker::dumpCachedGlyph(String8& log, const CachedGlyph& glyph) {
log.appendFormat("glyph (texture %p, position: (%d, %d), size: %dx%d, gen: %d)", glyph.texture,
- glyph.startX, glyph.startY, glyph.bitmapW, glyph.bitmapH, glyph.generation);
+ glyph.startX, glyph.startY, glyph.bitmapW, glyph.bitmapH, glyph.generation);
}
void FontCacheHistoryTracker::dumpRenderEntry(String8& log, const RenderEntry& entry) {
@@ -40,7 +40,7 @@ void FontCacheHistoryTracker::dumpRenderEntry(String8& log, const RenderEntry& e
void FontCacheHistoryTracker::dumpUploadEntry(String8& log, const CachedGlyph& glyph) {
if (glyph.bitmapW == 0 && glyph.bitmapH == 0) {
log.appendFormat(" cleared cachetexture %p in gen %d\n", glyph.texture,
- glyph.generation);
+ glyph.generation);
} else {
log.appendFormat(" uploaded ");
dumpCachedGlyph(log, glyph);
@@ -73,7 +73,7 @@ void FontCacheHistoryTracker::glyphRendered(CachedGlyphInfo* glyphInfo, int penX
}
void FontCacheHistoryTracker::glyphUploaded(CacheTexture* texture, uint32_t x, uint32_t y,
- uint16_t glyphW, uint16_t glyphH) {
+ uint16_t glyphW, uint16_t glyphH) {
CachedGlyph& glyph = mUploadHistory.next();
glyph.generation = generation;
glyph.texture = texture;
@@ -96,5 +96,5 @@ void FontCacheHistoryTracker::glyphsCleared(CacheTexture* texture) {
void FontCacheHistoryTracker::frameCompleted() {
generation++;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/font/FontCacheHistoryTracker.h b/libs/hwui/font/FontCacheHistoryTracker.h
index f1d9b9f10dc0..4b9ceccc09c9 100644
--- a/libs/hwui/font/FontCacheHistoryTracker.h
+++ b/libs/hwui/font/FontCacheHistoryTracker.h
@@ -35,6 +35,7 @@ public:
void frameCompleted();
void dump(String8& log) const;
+
private:
struct CachedGlyph {
void* texture;
@@ -60,5 +61,5 @@ private:
uint16_t generation = 0;
};
-}; // namespace uirenderer
-}; // namespace android \ No newline at end of file
+}; // namespace uirenderer
+}; // namespace android \ No newline at end of file
diff --git a/libs/hwui/font/FontUtil.h b/libs/hwui/font/FontUtil.h
index d4b4ff949f5a..596e153db6a9 100644
--- a/libs/hwui/font/FontUtil.h
+++ b/libs/hwui/font/FontUtil.h
@@ -26,11 +26,11 @@
///////////////////////////////////////////////////////////////////////////////
#ifdef TEXTURE_BORDER_SIZE
- #if TEXTURE_BORDER_SIZE != 1
- #error TEXTURE_BORDER_SIZE other than 1 is not currently supported
- #endif
+#if TEXTURE_BORDER_SIZE != 1
+#error TEXTURE_BORDER_SIZE other than 1 is not currently supported
+#endif
#else
- #define TEXTURE_BORDER_SIZE 1
+#define TEXTURE_BORDER_SIZE 1
#endif
#define CACHE_BLOCK_ROUNDING_SIZE 4
@@ -43,4 +43,4 @@ typedef uint16_t glyph_t;
// [-1, 1]. Result is an integral float.
#define AUTO_KERN(prev, next) static_cast<float>(((next) - (prev) + 32) >> 6)
-#endif // ANDROID_HWUI_FONT_UTIL_H
+#endif // ANDROID_HWUI_FONT_UTIL_H
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
new file mode 100644
index 000000000000..007961a6bedb
--- /dev/null
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AnimatedImageDrawable.h"
+#include "AnimatedImageThread.h"
+
+#include "utils/TraceUtils.h"
+
+#include <SkPicture.h>
+#include <SkRefCnt.h>
+#include <SkTLazy.h>
+
+namespace android {
+
+AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
+ : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed) {
+ mTimeToShowNextSnapshot = ms2ns(mSkAnimatedImage->currentFrameDuration());
+}
+
+void AnimatedImageDrawable::syncProperties() {
+ mProperties = mStagingProperties;
+}
+
+bool AnimatedImageDrawable::start() {
+ if (mRunning) {
+ return false;
+ }
+
+ mStarting = true;
+
+ mRunning = true;
+ return true;
+}
+
+bool AnimatedImageDrawable::stop() {
+ bool wasRunning = mRunning;
+ mRunning = false;
+ return wasRunning;
+}
+
+bool AnimatedImageDrawable::isRunning() {
+ return mRunning;
+}
+
+bool AnimatedImageDrawable::nextSnapshotReady() const {
+ return mNextSnapshot.valid() &&
+ mNextSnapshot.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
+}
+
+// Only called on the RenderThread while UI thread is locked.
+bool AnimatedImageDrawable::isDirty(nsecs_t* outDelay) {
+ *outDelay = 0;
+ const nsecs_t currentTime = systemTime(CLOCK_MONOTONIC);
+ const nsecs_t lastWallTime = mLastWallTime;
+
+ mLastWallTime = currentTime;
+ if (!mRunning) {
+ return false;
+ }
+
+ std::unique_lock lock{mSwapLock};
+ mCurrentTime += currentTime - lastWallTime;
+
+ if (!mNextSnapshot.valid()) {
+ // Need to trigger onDraw in order to start decoding the next frame.
+ *outDelay = mTimeToShowNextSnapshot - mCurrentTime;
+ return true;
+ }
+
+ if (mTimeToShowNextSnapshot > mCurrentTime) {
+ *outDelay = mTimeToShowNextSnapshot - mCurrentTime;
+ } else if (nextSnapshotReady()) {
+ // We have not yet updated mTimeToShowNextSnapshot. Read frame duration
+ // directly from mSkAnimatedImage.
+ lock.unlock();
+ std::unique_lock imageLock{mImageLock};
+ *outDelay = ms2ns(mSkAnimatedImage->currentFrameDuration());
+ return true;
+ } else {
+ // The next snapshot has not yet been decoded, but we've already passed
+ // time to draw it. There's not a good way to know when decoding will
+ // finish, so request an update immediately.
+ *outDelay = 0;
+ }
+
+ return false;
+}
+
+// Only called on the AnimatedImageThread.
+AnimatedImageDrawable::Snapshot AnimatedImageDrawable::decodeNextFrame() {
+ Snapshot snap;
+ {
+ std::unique_lock lock{mImageLock};
+ snap.mDurationMS = mSkAnimatedImage->decodeNextFrame();
+ snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
+ }
+
+ return snap;
+}
+
+// Only called on the AnimatedImageThread.
+AnimatedImageDrawable::Snapshot AnimatedImageDrawable::reset() {
+ Snapshot snap;
+ {
+ std::unique_lock lock{mImageLock};
+ mSkAnimatedImage->reset();
+ snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
+ snap.mDurationMS = mSkAnimatedImage->currentFrameDuration();
+ }
+
+ return snap;
+}
+
+// Only called on the RenderThread.
+void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
+ SkTLazy<SkPaint> lazyPaint;
+ SkAutoCanvasRestore acr(canvas, false);
+ if (mProperties.mAlpha != SK_AlphaOPAQUE || mProperties.mColorFilter.get()) {
+ lazyPaint.init();
+ lazyPaint.get()->setAlpha(mProperties.mAlpha);
+ lazyPaint.get()->setColorFilter(mProperties.mColorFilter);
+ lazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
+ }
+ if (mProperties.mMirrored) {
+ canvas->save();
+ canvas->translate(mSkAnimatedImage->getBounds().width(), 0);
+ canvas->scale(-1, 1);
+ }
+
+ const bool starting = mStarting;
+ mStarting = false;
+
+ const bool drawDirectly = !mSnapshot.mPic;
+ if (drawDirectly) {
+ // The image is not animating, and never was. Draw directly from
+ // mSkAnimatedImage.
+ if (lazyPaint.isValid()) {
+ canvas->saveLayer(mSkAnimatedImage->getBounds(), lazyPaint.get());
+ }
+
+ std::unique_lock lock{mImageLock};
+ mSkAnimatedImage->draw(canvas);
+ if (!mRunning) {
+ return;
+ }
+ } else if (starting) {
+ // The image has animated, and now is being reset. Queue up the first
+ // frame, but keep showing the current frame until the first is ready.
+ auto& thread = uirenderer::AnimatedImageThread::getInstance();
+ mNextSnapshot = thread.reset(sk_ref_sp(this));
+ }
+
+ bool finalFrame = false;
+ if (mRunning && nextSnapshotReady()) {
+ std::unique_lock lock{mSwapLock};
+ if (mCurrentTime >= mTimeToShowNextSnapshot) {
+ mSnapshot = mNextSnapshot.get();
+ const nsecs_t timeToShowCurrentSnap = mTimeToShowNextSnapshot;
+ if (mSnapshot.mDurationMS == SkAnimatedImage::kFinished) {
+ finalFrame = true;
+ mRunning = false;
+ } else {
+ mTimeToShowNextSnapshot += ms2ns(mSnapshot.mDurationMS);
+ if (mCurrentTime >= mTimeToShowNextSnapshot) {
+ // This would mean showing the current frame very briefly. It's
+ // possible that not being displayed for a time resulted in
+ // mCurrentTime being far ahead. Prevent showing many frames
+ // rapidly by going back to the beginning of this frame time.
+ mCurrentTime = timeToShowCurrentSnap;
+ }
+ }
+ }
+ }
+
+ if (mRunning && !mNextSnapshot.valid()) {
+ auto& thread = uirenderer::AnimatedImageThread::getInstance();
+ mNextSnapshot = thread.decodeNextFrame(sk_ref_sp(this));
+ }
+
+ if (!drawDirectly) {
+ // No other thread will modify mCurrentSnap so this should be safe to
+ // use without locking.
+ canvas->drawPicture(mSnapshot.mPic, nullptr, lazyPaint.getMaybeNull());
+ }
+
+ if (finalFrame) {
+ if (mEndListener) {
+ mEndListener->onAnimationEnd();
+ }
+ }
+}
+
+int AnimatedImageDrawable::drawStaging(SkCanvas* canvas) {
+ SkAutoCanvasRestore acr(canvas, false);
+ if (mStagingProperties.mAlpha != SK_AlphaOPAQUE || mStagingProperties.mColorFilter.get()) {
+ SkPaint paint;
+ paint.setAlpha(mStagingProperties.mAlpha);
+ paint.setColorFilter(mStagingProperties.mColorFilter);
+ canvas->saveLayer(mSkAnimatedImage->getBounds(), &paint);
+ }
+ if (mStagingProperties.mMirrored) {
+ canvas->save();
+ canvas->translate(mSkAnimatedImage->getBounds().width(), 0);
+ canvas->scale(-1, 1);
+ }
+
+ if (!mRunning) {
+ // Continue drawing the current frame, and return 0 to indicate no need
+ // to redraw.
+ std::unique_lock lock{mImageLock};
+ canvas->drawDrawable(mSkAnimatedImage.get());
+ return 0;
+ }
+
+ if (mStarting) {
+ mStarting = false;
+ int durationMS = 0;
+ {
+ std::unique_lock lock{mImageLock};
+ mSkAnimatedImage->reset();
+ durationMS = mSkAnimatedImage->currentFrameDuration();
+ }
+ {
+ std::unique_lock lock{mSwapLock};
+ mLastWallTime = 0;
+ // The current time will be added later, below.
+ mTimeToShowNextSnapshot = ms2ns(durationMS);
+ }
+ }
+
+ bool update = false;
+ {
+ const nsecs_t currentTime = systemTime(CLOCK_MONOTONIC);
+ std::unique_lock lock{mSwapLock};
+ // mLastWallTime starts off at 0. If it is still 0, just update it to
+ // the current time and avoid updating
+ if (mLastWallTime == 0) {
+ mCurrentTime = currentTime;
+ // mTimeToShowNextSnapshot is already set to the duration of the
+ // first frame.
+ mTimeToShowNextSnapshot += currentTime;
+ } else if (mRunning) {
+ mCurrentTime += currentTime - mLastWallTime;
+ update = mCurrentTime >= mTimeToShowNextSnapshot;
+ }
+ mLastWallTime = currentTime;
+ }
+
+ int durationMS = 0;
+ {
+ std::unique_lock lock{mImageLock};
+ if (update) {
+ durationMS = mSkAnimatedImage->decodeNextFrame();
+ }
+
+ canvas->drawDrawable(mSkAnimatedImage.get());
+ }
+
+ std::unique_lock lock{mSwapLock};
+ if (update) {
+ if (durationMS == SkAnimatedImage::kFinished) {
+ mRunning = false;
+ return SkAnimatedImage::kFinished;
+ }
+
+ const nsecs_t timeToShowCurrentSnapshot = mTimeToShowNextSnapshot;
+ mTimeToShowNextSnapshot += ms2ns(durationMS);
+ if (mCurrentTime >= mTimeToShowNextSnapshot) {
+ // As in onDraw, prevent speedy catch-up behavior.
+ mCurrentTime = timeToShowCurrentSnapshot;
+ }
+ }
+
+ return ns2ms(mTimeToShowNextSnapshot - mCurrentTime);
+}
+
+} // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
new file mode 100644
index 000000000000..115c45ae4bcb
--- /dev/null
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cutils/compiler.h>
+#include <utils/Macros.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <SkAnimatedImage.h>
+#include <SkCanvas.h>
+#include <SkColorFilter.h>
+#include <SkDrawable.h>
+#include <SkPicture.h>
+
+#include <future>
+#include <mutex>
+
+namespace android {
+
+class OnAnimationEndListener {
+public:
+ virtual ~OnAnimationEndListener() {}
+
+ virtual void onAnimationEnd() = 0;
+};
+
+/**
+ * Native component of android.graphics.drawable.AnimatedImageDrawables.java.
+ * This class can be drawn into Canvas.h and maintains the state needed to drive
+ * the animation from the RenderThread.
+ */
+class ANDROID_API AnimatedImageDrawable : public SkDrawable {
+public:
+ // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the
+ // Snapshots.
+ AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed);
+
+ /**
+ * This updates the internal time and returns true if the image needs
+ * to be redrawn this frame.
+ *
+ * This is called on RenderThread, while the UI thread is locked.
+ *
+ * @param outDelay Nanoseconds in the future when the following frame
+ * will need to be drawn. 0 if not running.
+ */
+ bool isDirty(nsecs_t* outDelay);
+
+ int getStagingAlpha() const { return mStagingProperties.mAlpha; }
+ void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; }
+ void setStagingColorFilter(sk_sp<SkColorFilter> filter) {
+ mStagingProperties.mColorFilter = filter;
+ }
+ void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; }
+ void syncProperties();
+
+ virtual SkRect onGetBounds() override { return mSkAnimatedImage->getBounds(); }
+
+ // Draw to software canvas, and return time to next draw.
+ // 0 means the animation is not running.
+ // -1 means the animation advanced to the final frame.
+ int drawStaging(SkCanvas* canvas);
+
+ // Returns true if the animation was started; false otherwise (e.g. it was
+ // already running)
+ bool start();
+ // Returns true if the animation was stopped; false otherwise (e.g. it was
+ // already stopped)
+ bool stop();
+ bool isRunning();
+ int getRepetitionCount() const { return mSkAnimatedImage->getRepetitionCount(); }
+ void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); }
+
+ void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) {
+ mEndListener = std::move(listener);
+ }
+
+ struct Snapshot {
+ sk_sp<SkPicture> mPic;
+ int mDurationMS;
+
+ Snapshot() = default;
+
+ Snapshot(Snapshot&&) = default;
+ Snapshot& operator=(Snapshot&&) = default;
+
+ PREVENT_COPY_AND_ASSIGN(Snapshot);
+ };
+
+ // These are only called on AnimatedImageThread.
+ Snapshot decodeNextFrame();
+ Snapshot reset();
+
+ size_t byteSize() const {
+ return sizeof(this) + mBytesUsed;
+ }
+
+protected:
+ virtual void onDraw(SkCanvas* canvas) override;
+
+private:
+ sk_sp<SkAnimatedImage> mSkAnimatedImage;
+ const size_t mBytesUsed;
+
+ bool mRunning = false;
+ bool mStarting = false;
+
+ // A snapshot of the current frame to draw.
+ Snapshot mSnapshot;
+
+ std::future<Snapshot> mNextSnapshot;
+
+ bool nextSnapshotReady() const;
+
+ // When to switch from mSnapshot to mNextSnapshot.
+ nsecs_t mTimeToShowNextSnapshot = 0;
+
+ // The current time for the drawable itself.
+ nsecs_t mCurrentTime = 0;
+
+ // The wall clock of the last time we called isDirty.
+ nsecs_t mLastWallTime = 0;
+
+ // Locked when assigning snapshots and times. Operations while this is held
+ // should be short.
+ std::mutex mSwapLock;
+
+ // Locked when mSkAnimatedImage is being updated or drawn.
+ std::mutex mImageLock;
+
+ struct Properties {
+ int mAlpha = SK_AlphaOPAQUE;
+ sk_sp<SkColorFilter> mColorFilter;
+ bool mMirrored = false;
+
+ Properties() = default;
+ Properties(Properties&) = default;
+ Properties& operator=(Properties&) = default;
+ };
+
+ Properties mStagingProperties;
+ Properties mProperties;
+
+ std::unique_ptr<OnAnimationEndListener> mEndListener;
+};
+
+} // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageThread.cpp b/libs/hwui/hwui/AnimatedImageThread.cpp
new file mode 100644
index 000000000000..c8990039875e
--- /dev/null
+++ b/libs/hwui/hwui/AnimatedImageThread.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AnimatedImageThread.h"
+
+#include <sys/resource.h>
+
+namespace android {
+namespace uirenderer {
+
+AnimatedImageThread& AnimatedImageThread::getInstance() {
+ static AnimatedImageThread* sInstance = new AnimatedImageThread();
+ return *sInstance;
+}
+
+AnimatedImageThread::AnimatedImageThread() {
+ setpriority(PRIO_PROCESS, 0, PRIORITY_NORMAL + PRIORITY_MORE_FAVORABLE);
+ start("AnimatedImageThread");
+}
+
+std::future<AnimatedImageDrawable::Snapshot> AnimatedImageThread::decodeNextFrame(
+ const sk_sp<AnimatedImageDrawable>& drawable) {
+ return queue().async([drawable]() { return drawable->decodeNextFrame(); });
+}
+
+std::future<AnimatedImageDrawable::Snapshot> AnimatedImageThread::reset(
+ const sk_sp<AnimatedImageDrawable>& drawable) {
+ return queue().async([drawable]() { return drawable->reset(); });
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageThread.h b/libs/hwui/hwui/AnimatedImageThread.h
new file mode 100644
index 000000000000..9e3537430d5a
--- /dev/null
+++ b/libs/hwui/hwui/AnimatedImageThread.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANIMATEDIMAGETHREAD_H_
+#define ANIMATEDIMAGETHREAD_H_
+
+#include "AnimatedImageDrawable.h"
+#include "thread/ThreadBase.h"
+
+#include <SkRefCnt.h>
+
+namespace android {
+
+namespace uirenderer {
+
+class AnimatedImageThread : private ThreadBase {
+ PREVENT_COPY_AND_ASSIGN(AnimatedImageThread);
+
+public:
+ static AnimatedImageThread& getInstance();
+
+ std::future<AnimatedImageDrawable::Snapshot> decodeNextFrame(
+ const sk_sp<AnimatedImageDrawable>&);
+ std::future<AnimatedImageDrawable::Snapshot> reset(const sk_sp<AnimatedImageDrawable>&);
+
+private:
+ AnimatedImageThread();
+};
+
+} // namespace uirenderer
+
+} // namespace android
+
+#endif // ANIMATEDIMAGETHREAD_H_
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 75b6d233643d..263d249d20e9 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -17,37 +17,37 @@
#include "Caches.h"
#include "renderthread/EglManager.h"
-#include "renderthread/RenderThread.h"
#include "renderthread/RenderProxy.h"
+#include "renderthread/RenderThread.h"
#include "utils/Color.h"
#include <sys/mman.h>
-#include <log/log.h>
#include <cutils/ashmem.h>
+#include <log/log.h>
-#include <private/gui/ComposerService.h>
#include <binder/IServiceManager.h>
+#include <private/gui/ComposerService.h>
#include <ui/PixelFormat.h>
#include <SkCanvas.h>
#include <SkImagePriv.h>
+#include <SkToSRGBColorFilter.h>
namespace android {
static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
int32_t rowBytes32 = SkToS32(rowBytes);
- int64_t bigSize = (int64_t) height * rowBytes32;
+ int64_t bigSize = (int64_t)height * rowBytes32;
if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
- return false; // allocation will be too large
+ return false; // allocation will be too large
}
*size = sk_64_asS32(bigSize);
return true;
}
-typedef sk_sp<Bitmap> (*AllocPixelRef)(size_t allocSize, const SkImageInfo& info,
- size_t rowBytes);
+typedef sk_sp<Bitmap> (*AllocPixelRef)(size_t allocSize, const SkImageInfo& info, size_t rowBytes);
static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, AllocPixelRef alloc) {
const SkImageInfo& info = bitmap->info();
@@ -73,7 +73,7 @@ static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, AllocPixelRef alloc) {
}
sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap) {
- return allocateBitmap(bitmap, &Bitmap::allocateAshmemBitmap);
+ return allocateBitmap(bitmap, &Bitmap::allocateAshmemBitmap);
}
static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes) {
@@ -89,7 +89,7 @@ sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(SkBitmap& bitmap) {
}
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap) {
- return allocateBitmap(bitmap, &android::allocateHeapBitmap);
+ return allocateBitmap(bitmap, &android::allocateHeapBitmap);
}
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(const SkImageInfo& info) {
@@ -101,8 +101,7 @@ sk_sp<Bitmap> Bitmap::allocateHeapBitmap(const SkImageInfo& info) {
return android::allocateHeapBitmap(size, info, info.minRowBytes());
}
-sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info,
- size_t rowBytes) {
+sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info, size_t rowBytes) {
// Create new ashmem region with read/write priv
int fd = ashmem_create_region("bitmap", size);
if (fd < 0) {
@@ -124,25 +123,25 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info,
}
void FreePixelRef(void* addr, void* context) {
- auto pixelRef = (SkPixelRef*) context;
+ auto pixelRef = (SkPixelRef*)context;
pixelRef->unref();
}
sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, SkPixelRef& pixelRef) {
pixelRef.ref();
- return sk_sp<Bitmap>(new Bitmap((void*) pixelRef.pixels(), (void*) &pixelRef, FreePixelRef,
- info, pixelRef.rowBytes()));
+ return sk_sp<Bitmap>(new Bitmap((void*)pixelRef.pixels(), (void*)&pixelRef, FreePixelRef, info,
+ pixelRef.rowBytes()));
}
sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
PixelFormat format = graphicBuffer->getPixelFormat();
if (!graphicBuffer.get() ||
- (format != PIXEL_FORMAT_RGBA_8888 && format != PIXEL_FORMAT_RGBA_FP16)) {
+ (format != PIXEL_FORMAT_RGBA_8888 && format != PIXEL_FORMAT_RGBA_FP16)) {
return nullptr;
}
SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
- kRGBA_8888_SkColorType, kPremul_SkAlphaType,
- SkColorSpace::MakeSRGB());
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType,
+ SkColorSpace::MakeSRGB());
return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
}
@@ -154,8 +153,8 @@ static SkImageInfo validateAlpha(const SkImageInfo& info) {
// Need to validate the alpha type to filter against the color type
// to prevent things like a non-opaque RGB565 bitmap
SkAlphaType alphaType;
- LOG_ALWAYS_FATAL_IF(!SkColorTypeValidateAlphaType(
- info.colorType(), info.alphaType(), &alphaType),
+ LOG_ALWAYS_FATAL_IF(
+ !SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &alphaType),
"Failed to validate alpha type!");
return info.makeAlphaType(alphaType);
}
@@ -172,28 +171,27 @@ void Bitmap::reconfigure(const SkImageInfo& newInfo, size_t rowBytes) {
}
Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBytes)
- : SkPixelRef(info.width(), info.height(), address, rowBytes)
- , mInfo(validateAlpha(info))
- , mPixelStorageType(PixelStorageType::Heap) {
+ : SkPixelRef(info.width(), info.height(), address, rowBytes)
+ , mInfo(validateAlpha(info))
+ , mPixelStorageType(PixelStorageType::Heap) {
mPixelStorage.heap.address = address;
mPixelStorage.heap.size = size;
}
-Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc,
- const SkImageInfo& info, size_t rowBytes)
- : SkPixelRef(info.width(), info.height(), address, rowBytes)
- , mInfo(validateAlpha(info))
- , mPixelStorageType(PixelStorageType::External) {
+Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info,
+ size_t rowBytes)
+ : SkPixelRef(info.width(), info.height(), address, rowBytes)
+ , mInfo(validateAlpha(info))
+ , mPixelStorageType(PixelStorageType::External) {
mPixelStorage.external.address = address;
mPixelStorage.external.context = context;
mPixelStorage.external.freeFunc = freeFunc;
}
-Bitmap::Bitmap(void* address, int fd, size_t mappedSize,
- const SkImageInfo& info, size_t rowBytes)
- : SkPixelRef(info.width(), info.height(), address, rowBytes)
- , mInfo(validateAlpha(info))
- , mPixelStorageType(PixelStorageType::Ashmem) {
+Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes)
+ : SkPixelRef(info.width(), info.height(), address, rowBytes)
+ , mInfo(validateAlpha(info))
+ , mPixelStorageType(PixelStorageType::Ashmem) {
mPixelStorage.ashmem.address = address;
mPixelStorage.ashmem.fd = fd;
mPixelStorage.ashmem.size = mappedSize;
@@ -206,35 +204,31 @@ Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info)
, mPixelStorageType(PixelStorageType::Hardware) {
mPixelStorage.hardware.buffer = buffer;
buffer->incStrong(buffer);
- setImmutable(); // HW bitmaps are always immutable
+ setImmutable(); // HW bitmaps are always immutable
if (uirenderer::Properties::isSkiaEnabled()) {
- // GraphicBuffer should be in the display color space (Bitmap::createFrom is always
- // passing SRGB). The code that uploads into a GraphicBuffer should do color conversion if
- // needed.
mImage = SkImage::MakeFromAHardwareBuffer(reinterpret_cast<AHardwareBuffer*>(buffer),
- mInfo.alphaType(), nullptr);
+ mInfo.alphaType(), mInfo.refColorSpace());
}
}
Bitmap::~Bitmap() {
switch (mPixelStorageType) {
- case PixelStorageType::External:
- mPixelStorage.external.freeFunc(mPixelStorage.external.address,
- mPixelStorage.external.context);
- break;
- case PixelStorageType::Ashmem:
- munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
- close(mPixelStorage.ashmem.fd);
- break;
- case PixelStorageType::Heap:
- free(mPixelStorage.heap.address);
- break;
- case PixelStorageType::Hardware:
- auto buffer = mPixelStorage.hardware.buffer;
- buffer->decStrong(buffer);
- mPixelStorage.hardware.buffer = nullptr;
- break;
-
+ case PixelStorageType::External:
+ mPixelStorage.external.freeFunc(mPixelStorage.external.address,
+ mPixelStorage.external.context);
+ break;
+ case PixelStorageType::Ashmem:
+ munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
+ close(mPixelStorage.ashmem.fd);
+ break;
+ case PixelStorageType::Heap:
+ free(mPixelStorage.heap.address);
+ break;
+ case PixelStorageType::Hardware:
+ auto buffer = mPixelStorage.hardware.buffer;
+ buffer->decStrong(buffer);
+ mPixelStorage.hardware.buffer = nullptr;
+ break;
}
android::uirenderer::renderthread::RenderProxy::onBitmapDestroyed(getStableID());
@@ -250,32 +244,32 @@ void Bitmap::setHasHardwareMipMap(bool hasMipMap) {
void* Bitmap::getStorage() const {
switch (mPixelStorageType) {
- case PixelStorageType::External:
- return mPixelStorage.external.address;
- case PixelStorageType::Ashmem:
- return mPixelStorage.ashmem.address;
- case PixelStorageType::Heap:
- return mPixelStorage.heap.address;
- case PixelStorageType::Hardware:
- return nullptr;
+ case PixelStorageType::External:
+ return mPixelStorage.external.address;
+ case PixelStorageType::Ashmem:
+ return mPixelStorage.ashmem.address;
+ case PixelStorageType::Heap:
+ return mPixelStorage.heap.address;
+ case PixelStorageType::Hardware:
+ return nullptr;
}
}
int Bitmap::getAshmemFd() const {
switch (mPixelStorageType) {
- case PixelStorageType::Ashmem:
- return mPixelStorage.ashmem.fd;
- default:
- return -1;
+ case PixelStorageType::Ashmem:
+ return mPixelStorage.ashmem.fd;
+ default:
+ return -1;
}
}
size_t Bitmap::getAllocationByteCount() const {
switch (mPixelStorageType) {
- case PixelStorageType::Heap:
- return mPixelStorage.heap.size;
- default:
- return rowBytes() * height();
+ case PixelStorageType::Heap:
+ return mPixelStorage.heap.size;
+ default:
+ return rowBytes() * height();
}
}
@@ -296,11 +290,17 @@ void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
if (isHardware()) {
if (uirenderer::Properties::isSkiaEnabled()) {
outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
- info().colorType(), info().alphaType(), nullptr));
+ info().colorType(), info().alphaType(),
+ nullptr));
} else {
outBitmap->allocPixels(info());
}
uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
+ if (mInfo.colorSpace()) {
+ sk_sp<SkPixelRef> pixelRef = sk_ref_sp(outBitmap->pixelRef());
+ outBitmap->setInfo(mInfo);
+ outBitmap->setPixelRef(std::move(pixelRef), 0, 0);
+ }
return;
}
outBitmap->setInfo(mInfo, rowBytes());
@@ -319,7 +319,7 @@ GraphicBuffer* Bitmap::graphicBuffer() {
return nullptr;
}
-sk_sp<SkImage> Bitmap::makeImage() {
+sk_sp<SkImage> Bitmap::makeImage(sk_sp<SkColorFilter>* outputColorFilter) {
sk_sp<SkImage> image = mImage;
if (!image) {
SkASSERT(!(isHardware() && uirenderer::Properties::isSkiaEnabled()));
@@ -330,14 +330,13 @@ sk_sp<SkImage> Bitmap::makeImage() {
// Note we don't cache in this case, because the raster image holds a pointer to this Bitmap
// internally and ~Bitmap won't be invoked.
// TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here.
- if (uirenderer::Properties::isSkiaEnabled()) {
- image = SkMakeImageInColorSpace(skiaBitmap, SkColorSpace::MakeSRGB(),
- skiaBitmap.getGenerationID(), kNever_SkCopyPixelsMode);
- } else {
- image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
- }
+ image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+ }
+ if (uirenderer::Properties::isSkiaEnabled() && image->colorSpace() != nullptr &&
+ !image->colorSpace()->isSRGB()) {
+ *outputColorFilter = SkToSRGBColorFilter::Make(image->refColorSpace());
}
return image;
}
-} // namespace android
+} // namespace android
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 634e76450c38..4f06656e8e6d 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -16,13 +16,14 @@
#pragma once
#include <SkBitmap.h>
+#include <SkColorFilter.h>
#include <SkColorSpace.h>
#include <SkImage.h>
+#include <SkImage.h>
#include <SkImageInfo.h>
#include <SkPixelRef.h>
#include <cutils/compiler.h>
#include <ui/GraphicBuffer.h>
-#include <SkImage.h>
namespace android {
@@ -35,7 +36,7 @@ enum class PixelStorageType {
namespace uirenderer {
namespace renderthread {
- class RenderThread;
+class RenderThread;
}
}
@@ -52,21 +53,20 @@ public:
static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap);
static sk_sp<Bitmap> allocateAshmemBitmap(size_t allocSize, const SkImageInfo& info,
- size_t rowBytes);
+ size_t rowBytes);
static sk_sp<Bitmap> createFrom(sp<GraphicBuffer> graphicBuffer);
static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);
Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes);
- Bitmap(void* address, void* context, FreeFunc freeFunc,
- const SkImageInfo& info, size_t rowBytes);
- Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
- size_t rowBytes);
+ Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info,
+ size_t rowBytes);
+ Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes);
Bitmap(GraphicBuffer* buffer, const SkImageInfo& info);
int rowBytesAsPixels() const {
- return rowBytes() >> SkColorTypeShiftPerPixel(mInfo.colorType());
+ return rowBytes() >> mInfo.shiftPerPixel();
}
void reconfigure(const SkImageInfo& info, size_t rowBytes);
@@ -84,21 +84,27 @@ public:
bool isOpaque() const { return mInfo.isOpaque(); }
SkColorType colorType() const { return mInfo.colorType(); }
- const SkImageInfo& info() const {
- return mInfo;
- }
+ const SkImageInfo& info() const { return mInfo; }
void getBounds(SkRect* bounds) const;
- bool isHardware() const {
- return mPixelStorageType == PixelStorageType::Hardware;
- }
+ bool isHardware() const { return mPixelStorageType == PixelStorageType::Hardware; }
GraphicBuffer* graphicBuffer();
- // makeImage creates or returns a cached SkImage. Can be invoked from UI or render thread.
- // Caching is supported only for HW Bitmaps with skia pipeline.
- sk_sp<SkImage> makeImage();
+ /**
+ * Creates or returns a cached SkImage and is safe to be invoked from either
+ * the UI or RenderThread.
+ *
+ * @param outputColorFilter is a required param that will be populated by
+ * this function if the bitmap's colorspace is not sRGB. If populated the
+ * filter will convert colors from the bitmaps colorspace into sRGB. It
+ * is the callers responsibility to use this colorFilter when drawing
+ * this image into any destination that is presumed to be sRGB (i.e. a
+ * buffer that has no colorspace defined).
+ */
+ sk_sp<SkImage> makeImage(sk_sp<SkColorFilter>* outputColorFilter);
+
private:
virtual ~Bitmap();
void* getStorage() const;
@@ -129,7 +135,7 @@ private:
} hardware;
} mPixelStorage;
- sk_sp<SkImage> mImage; // Cache is used only for HW Bitmaps with Skia pipeline.
+ sk_sp<SkImage> mImage; // Cache is used only for HW Bitmaps with Skia pipeline.
};
-} //namespace android
+} // namespace android
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index e754daf7c42e..20543df85068 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -16,13 +16,13 @@
#include "Canvas.h"
-#include "RecordingCanvas.h"
-#include "RenderNode.h"
#include "MinikinUtils.h"
#include "Paint.h"
#include "Properties.h"
-#include "pipeline/skia/SkiaRecordingCanvas.h"
+#include "RecordingCanvas.h"
+#include "RenderNode.h"
#include "Typeface.h"
+#include "pipeline/skia/SkiaRecordingCanvas.h"
#include <SkDrawFilter.h>
@@ -36,7 +36,7 @@ Canvas* Canvas::create_recording_canvas(int width, int height, uirenderer::Rende
}
static inline void drawStroke(SkScalar left, SkScalar right, SkScalar top, SkScalar thickness,
- const SkPaint& paint, Canvas* canvas) {
+ const SkPaint& paint, Canvas* canvas) {
const SkScalar strokeWidth = fmax(thickness, 1.0f);
const SkScalar bottom = top + strokeWidth;
canvas->drawRect(left, top, right, bottom, paint);
@@ -91,20 +91,18 @@ static void simplifyPaint(int color, SkPaint* paint) {
class DrawTextFunctor {
public:
- DrawTextFunctor(const minikin::Layout& layout, Canvas* canvas,
- const SkPaint& paint, float x, float y, minikin::MinikinRect& bounds,
- float totalAdvance)
- : layout(layout)
- , canvas(canvas)
- , paint(paint)
- , x(x)
- , y(y)
- , bounds(bounds)
- , totalAdvance(totalAdvance) {
- }
+ DrawTextFunctor(const minikin::Layout& layout, Canvas* canvas, const SkPaint& paint, float x,
+ float y, minikin::MinikinRect& bounds, float totalAdvance)
+ : layout(layout)
+ , canvas(canvas)
+ , paint(paint)
+ , x(x)
+ , y(y)
+ , bounds(bounds)
+ , totalAdvance(totalAdvance) {}
void operator()(size_t start, size_t end) {
- auto glyphFunc = [&] (uint16_t* text, float* positions) {
+ auto glyphFunc = [&](uint16_t* text, float* positions) {
if (canvas->drawTextAbsolutePos()) {
for (size_t i = start, textIndex = 0, posIndex = 0; i < end; i++) {
text[textIndex++] = layout.getGlyphId(i);
@@ -133,20 +131,21 @@ public:
simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
canvas->drawGlyphs(glyphFunc, glyphCount, outlinePaint, x, y, bounds.mLeft, bounds.mTop,
- bounds.mRight, bounds.mBottom, totalAdvance);
+ bounds.mRight, bounds.mBottom, totalAdvance);
// inner
SkPaint innerPaint(paint);
simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
innerPaint.setStyle(SkPaint::kFill_Style);
canvas->drawGlyphs(glyphFunc, glyphCount, innerPaint, x, y, bounds.mLeft, bounds.mTop,
- bounds.mRight, bounds.mBottom, totalAdvance);
+ bounds.mRight, bounds.mBottom, totalAdvance);
} else {
// standard draw path
canvas->drawGlyphs(glyphFunc, glyphCount, paint, x, y, bounds.mLeft, bounds.mTop,
- bounds.mRight, bounds.mBottom, totalAdvance);
+ bounds.mRight, bounds.mBottom, totalAdvance);
}
}
+
private:
const minikin::Layout& layout;
Canvas* canvas;
@@ -157,13 +156,15 @@ private:
float totalAdvance;
};
-void Canvas::drawText(const uint16_t* text, int start, int count, int contextCount,
- float x, float y, int bidiFlags, const Paint& origPaint, Typeface* typeface) {
+void Canvas::drawText(const uint16_t* text, int start, int count, int contextCount, float x,
+ float y, minikin::Bidi bidiFlags, const Paint& origPaint,
+ const Typeface* typeface, minikin::MeasuredText* mt) {
// minikin may modify the original paint
Paint paint(origPaint);
- minikin::Layout layout = MinikinUtils::doLayout(
- &paint, bidiFlags, typeface, text, start, count, contextCount);
+ minikin::Layout layout =
+ MinikinUtils::doLayout(&paint, bidiFlags, typeface, text, start, count, contextCount,
+ mt);
x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
@@ -185,18 +186,18 @@ void Canvas::drawText(const uint16_t* text, int start, int count, int contextCou
class DrawTextOnPathFunctor {
public:
DrawTextOnPathFunctor(const minikin::Layout& layout, Canvas* canvas, float hOffset,
- float vOffset, const Paint& paint, const SkPath& path)
- : layout(layout)
- , canvas(canvas)
- , hOffset(hOffset)
- , vOffset(vOffset)
- , paint(paint)
- , path(path) {
- }
+ float vOffset, const Paint& paint, const SkPath& path)
+ : layout(layout)
+ , canvas(canvas)
+ , hOffset(hOffset)
+ , vOffset(vOffset)
+ , paint(paint)
+ , path(path) {}
void operator()(size_t start, size_t end) {
canvas->drawLayoutOnPath(layout, hOffset, vOffset, paint, path, start, end);
}
+
private:
const minikin::Layout& layout;
Canvas* canvas;
@@ -206,11 +207,12 @@ private:
const SkPath& path;
};
-void Canvas::drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
- float hOffset, float vOffset, const Paint& paint, Typeface* typeface) {
+void Canvas::drawTextOnPath(const uint16_t* text, int count, minikin::Bidi bidiFlags,
+ const SkPath& path, float hOffset, float vOffset, const Paint& paint,
+ const Typeface* typeface) {
Paint paintCopy(paint);
- minikin::Layout layout = MinikinUtils::doLayout(
- &paintCopy, bidiFlags, typeface, text, 0, count, count);
+ minikin::Layout layout =
+ MinikinUtils::doLayout(&paintCopy, bidiFlags, typeface, text, 0, count, count, nullptr);
hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
// Set align to left for drawing, as we don't want individual
@@ -222,4 +224,10 @@ void Canvas::drawTextOnPath(const uint16_t* text, int count, int bidiFlags, cons
MinikinUtils::forFontRun(layout, &paintCopy, f);
}
-} // namespace android
+int Canvas::sApiLevel = 1;
+
+void Canvas::setCompatibilityVersion(int apiLevel) {
+ sApiLevel = apiLevel;
+}
+
+} // namespace android
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index ac8a08169997..f341cf96120d 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -19,46 +19,50 @@
#include <cutils/compiler.h>
#include <utils/Functor.h>
+#include <androidfw/ResourceTypes.h>
#include "GlFunctorLifecycleListener.h"
+#include "Properties.h"
#include "utils/Macros.h"
-#include <androidfw/ResourceTypes.h>
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkMatrix.h>
+class SkAnimatedImage;
class SkCanvasState;
class SkVertices;
namespace minikin {
- class Layout;
+class Layout;
+class MeasuredText;
+enum class Bidi : uint8_t;
}
namespace android {
namespace uirenderer {
- class CanvasPropertyPaint;
- class CanvasPropertyPrimitive;
- class DeferredLayerUpdater;
- class DisplayList;
- class RenderNode;
+class CanvasPropertyPaint;
+class CanvasPropertyPrimitive;
+class DeferredLayerUpdater;
+class DisplayList;
+class RenderNode;
}
namespace SaveFlags {
// These must match the corresponding Canvas API constants.
enum {
- Matrix = 0x01,
- Clip = 0x02,
+ Matrix = 0x01,
+ Clip = 0x02,
HasAlphaLayer = 0x04,
- ClipToLayer = 0x10,
+ ClipToLayer = 0x10,
// Helper constant
- MatrixClip = Matrix | Clip,
+ MatrixClip = Matrix | Clip,
};
typedef uint32_t Flags;
-} // namespace SaveFlags
+} // namespace SaveFlags
namespace uirenderer {
class SkiaCanvasProxy;
@@ -70,13 +74,14 @@ typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
typedef std::function<void(uint16_t* text, float* positions)> ReadGlyphFunc;
+class AnimatedImageDrawable;
class Bitmap;
class Paint;
struct Typeface;
class ANDROID_API Canvas {
public:
- virtual ~Canvas() {};
+ virtual ~Canvas(){};
static Canvas* create_canvas(const SkBitmap& bitmap);
@@ -95,17 +100,8 @@ public:
determined based on Properties::getRenderPipelineType().
*
*/
- static WARN_UNUSED_RESULT Canvas* create_recording_canvas(int width, int height,
- uirenderer::RenderNode* renderNode = nullptr);
-
- enum class XformToSRGB {
- // Transform any Bitmaps to the sRGB color space before drawing.
- kImmediate,
-
- // Draw the Bitmap as is. This likely means that we are recording and that the
- // transform can be handled at playback time.
- kDefer,
- };
+ static WARN_UNUSED_RESULT Canvas* create_recording_canvas(
+ int width, int height, uirenderer::RenderNode* renderNode = nullptr);
/**
* Create a new Canvas object which delegates to an SkCanvas.
@@ -114,12 +110,18 @@ public:
* delegated to this object. This function will call ref() on the
* SkCanvas, and the returned Canvas will unref() it upon
* destruction.
- * @param xformToSRGB Indicates if bitmaps should be xformed to the sRGB
- * color space before drawing.
* @return new non-null Canvas Object. The type of DisplayList produced by this canvas is
* determined based on Properties::getRenderPipelineType().
*/
- static Canvas* create_canvas(SkCanvas* skiaCanvas, XformToSRGB xformToSRGB);
+ static Canvas* create_canvas(SkCanvas* skiaCanvas);
+
+ /**
+ * Sets the target SDK version used to build the app.
+ *
+ * @param apiLevel API level
+ *
+ */
+ static void setCompatibilityVersion(int apiLevel);
/**
* Provides a Skia SkCanvas interface that acts as a proxy to this Canvas.
@@ -135,41 +137,43 @@ public:
*/
virtual SkCanvas* asSkCanvas() = 0;
-
virtual void setBitmap(const SkBitmap& bitmap) = 0;
virtual bool isOpaque() = 0;
virtual int width() = 0;
virtual int height() = 0;
-// ----------------------------------------------------------------------------
-// View System operations (not exposed in public Canvas API)
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // View System operations (not exposed in public Canvas API)
+ // ----------------------------------------------------------------------------
virtual void resetRecording(int width, int height,
- uirenderer::RenderNode* renderNode = nullptr) = 0;
+ uirenderer::RenderNode* renderNode = nullptr) = 0;
virtual uirenderer::DisplayList* finishRecording() = 0;
virtual void insertReorderBarrier(bool enableReorder) = 0;
- virtual void setHighContrastText(bool highContrastText) = 0;
- virtual bool isHighContrastText() = 0;
+ bool isHighContrastText() const { return uirenderer::Properties::enableHighContrastText; }
virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
- uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
- uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
- uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) = 0;
+ uirenderer::CanvasPropertyPrimitive* top,
+ uirenderer::CanvasPropertyPrimitive* right,
+ uirenderer::CanvasPropertyPrimitive* bottom,
+ uirenderer::CanvasPropertyPrimitive* rx,
+ uirenderer::CanvasPropertyPrimitive* ry,
+ uirenderer::CanvasPropertyPaint* paint) = 0;
virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x,
- uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
- uirenderer::CanvasPropertyPaint* paint) = 0;
+ uirenderer::CanvasPropertyPrimitive* y,
+ uirenderer::CanvasPropertyPrimitive* radius,
+ uirenderer::CanvasPropertyPaint* paint) = 0;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0;
virtual void callDrawGLFunction(Functor* functor,
- uirenderer::GlFunctorLifecycleListener* listener) = 0;
+ uirenderer::GlFunctorLifecycleListener* listener) = 0;
-// ----------------------------------------------------------------------------
-// Canvas state operations
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // Canvas state operations
+ // ----------------------------------------------------------------------------
// Save (layer)
virtual int getSaveCount() const = 0;
@@ -177,10 +181,10 @@ public:
virtual void restore() = 0;
virtual void restoreToCount(int saveCount) = 0;
- virtual int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SaveFlags::Flags flags) = 0;
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SaveFlags::Flags flags) = 0;
+ virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+ SaveFlags::Flags flags) = 0;
+ virtual int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
+ SaveFlags::Flags flags) = 0;
// Matrix
virtual void getMatrix(SkMatrix* outMatrix) const = 0;
@@ -197,8 +201,7 @@ public:
virtual bool quickRejectRect(float left, float top, float right, float bottom) const = 0;
virtual bool quickRejectPath(const SkPath& path) const = 0;
- virtual bool clipRect(float left, float top, float right, float bottom,
- SkClipOp op) = 0;
+ virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) = 0;
virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
// filters
@@ -208,9 +211,9 @@ public:
// WebView only
virtual SkCanvasState* captureCanvasState() const { return nullptr; }
-// ----------------------------------------------------------------------------
-// Canvas draw operations
-// ----------------------------------------------------------------------------
+ // ----------------------------------------------------------------------------
+ // Canvas draw operations
+ // ----------------------------------------------------------------------------
virtual void drawColor(int color, SkBlendMode mode) = 0;
virtual void drawPaint(const SkPaint& paint) = 0;
@@ -218,34 +221,34 @@ public:
virtual void drawPoint(float x, float y, const SkPaint& paint) = 0;
virtual void drawPoints(const float* points, int floatCount, const SkPaint& paint) = 0;
virtual void drawLine(float startX, float startY, float stopX, float stopY,
- const SkPaint& paint) = 0;
+ const SkPaint& paint) = 0;
virtual void drawLines(const float* points, int floatCount, const SkPaint& paint) = 0;
virtual void drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) = 0;
+ const SkPaint& paint) = 0;
virtual void drawRegion(const SkRegion& region, const SkPaint& paint) = 0;
- virtual void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) = 0;
+ virtual void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+ const SkPaint& paint) = 0;
virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) = 0;
virtual void drawOval(float left, float top, float right, float bottom,
- const SkPaint& paint) = 0;
- virtual void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) = 0;
+ const SkPaint& paint) = 0;
+ virtual void drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, bool useCenter, const SkPaint& paint) = 0;
virtual void drawPath(const SkPath& path, const SkPaint& paint) = 0;
virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint& paint) = 0;
// Bitmap-based
- virtual void drawBitmap(Bitmap& bitmap, float left, float top,
- const SkPaint* paint) = 0;
- virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix,
- const SkPaint* paint) = 0;
- virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) = 0;
+ virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) = 0;
+ virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) = 0;
+ virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) = 0;
virtual void drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) = 0;
- virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkPaint* paint) = 0;
+ const float* vertices, const int* colors, const SkPaint* paint) = 0;
+ virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk, float dstLeft,
+ float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) = 0;
+
+ virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) = 0;
/**
* Specifies if the positions passed to ::drawText are absolute or relative
@@ -265,11 +268,15 @@ public:
* Converts utf16 text to glyphs, calculating position and boundary,
* and delegating the final draw to virtual drawGlyphs method.
*/
- void drawText(const uint16_t* text, int start, int count, int contextCount,
- float x, float y, int bidiFlags, const Paint& origPaint, Typeface* typeface);
+ void drawText(const uint16_t* text, int start, int count, int contextCount, float x, float y,
+ minikin::Bidi bidiFlags, const Paint& origPaint, const Typeface* typeface,
+ minikin::MeasuredText* mt);
+
+ void drawTextOnPath(const uint16_t* text, int count, minikin::Bidi bidiFlags,
+ const SkPath& path, float hOffset, float vOffset, const Paint& paint,
+ const Typeface* typeface);
- void drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
- float hOffset, float vOffset, const Paint& paint, Typeface* typeface);
+ static int GetApiLevel() { return sApiLevel; }
protected:
void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
@@ -280,13 +287,16 @@ protected:
* totalAdvance: used to define width of text decorations (underlines, strikethroughs).
*/
virtual void drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& paint, float x,
- float y, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
- float totalAdvance) = 0;
+ float y, float boundsLeft, float boundsTop, float boundsRight,
+ float boundsBottom, float totalAdvance) = 0;
virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
- const SkPaint& paint, const SkPath& path, size_t start, size_t end) = 0;
+ const SkPaint& paint, const SkPath& path, size_t start,
+ size_t end) = 0;
+ static int sApiLevel;
+
friend class DrawTextFunctor;
friend class DrawTextOnPathFunctor;
friend class uirenderer::SkiaCanvasProxy;
};
-}; // namespace android
+}; // namespace android
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index ba4e3a4df578..5d33860bab6b 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -16,37 +16,41 @@
#include "MinikinSkia.h"
-#include <log/log.h>
#include <SkFontDescriptor.h>
#include <SkFontMgr.h>
#include <SkPaint.h>
#include <SkTypeface.h>
+#include <log/log.h>
namespace android {
MinikinFontSkia::MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
- int ttcIndex, const std::vector<minikin::FontVariation>& axes) :
- minikin::MinikinFont(typeface->uniqueID()), mTypeface(std::move(typeface)), mFontData(fontData),
- mFontSize(fontSize), mTtcIndex(ttcIndex), mAxes(axes) {
-}
+ int ttcIndex, const std::vector<minikin::FontVariation>& axes)
+ : minikin::MinikinFont(typeface->uniqueID())
+ , mTypeface(std::move(typeface))
+ , mFontData(fontData)
+ , mFontSize(fontSize)
+ , mTtcIndex(ttcIndex)
+ , mAxes(axes) {}
static void MinikinFontSkia_SetSkiaPaint(const minikin::MinikinFont* font, SkPaint* skPaint,
- const minikin::MinikinPaint& paint) {
+ const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) {
skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
skPaint->setTextSize(paint.size);
skPaint->setTextScaleX(paint.scaleX);
skPaint->setTextSkewX(paint.skewX);
MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags);
// Apply font fakery on top of user-supplied flags.
- MinikinFontSkia::populateSkPaint(skPaint, font, paint.fakery);
+ MinikinFontSkia::populateSkPaint(skPaint, font, fakery);
}
-float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
- const minikin::MinikinPaint &paint) const {
+float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id, const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) const {
SkPaint skPaint;
uint16_t glyph16 = glyph_id;
SkScalar skWidth;
- MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
+ MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint, fakery);
skPaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, NULL);
#ifdef VERBOSE
ALOGD("width for typeface %d glyph %d = %f", mTypeface->uniqueID(), glyph_id, skWidth);
@@ -55,11 +59,12 @@ float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
}
void MinikinFontSkia::GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
- const minikin::MinikinPaint& paint) const {
+ const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) const {
SkPaint skPaint;
uint16_t glyph16 = glyph_id;
SkRect skBounds;
- MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
+ MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint, fakery);
skPaint.getTextWidths(&glyph16, sizeof(glyph16), NULL, &skBounds);
bounds->mLeft = skBounds.fLeft;
bounds->mTop = skBounds.fTop;
@@ -67,7 +72,19 @@ void MinikinFontSkia::GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
bounds->mBottom = skBounds.fBottom;
}
-SkTypeface *MinikinFontSkia::GetSkTypeface() const {
+void MinikinFontSkia::GetFontExtent(minikin::MinikinExtent* extent,
+ const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) const {
+ SkPaint skPaint;
+ MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint, fakery);
+ SkPaint::FontMetrics metrics;
+ skPaint.getFontMetrics(&metrics);
+ extent->ascent = metrics.fAscent;
+ extent->descent = metrics.fDescent;
+ extent->line_gap = metrics.fLeading;
+}
+
+SkTypeface* MinikinFontSkia::GetSkTypeface() const {
return mTypeface.get();
}
@@ -93,14 +110,14 @@ const std::vector<minikin::FontVariation>& MinikinFontSkia::GetAxes() const {
std::shared_ptr<minikin::MinikinFont> MinikinFontSkia::createFontWithVariation(
const std::vector<minikin::FontVariation>& variations) const {
- SkFontMgr::FontParameters params;
+ SkFontArguments params;
int ttcIndex;
- SkStreamAsset* stream = mTypeface->openStream(&ttcIndex);
+ std::unique_ptr<SkStreamAsset> stream(mTypeface->openStream(&ttcIndex));
LOG_ALWAYS_FATAL_IF(stream == nullptr, "openStream failed");
params.setCollectionIndex(ttcIndex);
- std::vector<SkFontMgr::FontParameters::Axis> skAxes;
+ std::vector<SkFontArguments::Axis> skAxes;
skAxes.resize(variations.size());
for (size_t i = 0; i < variations.size(); i++) {
skAxes[i].fTag = variations[i].axisTag;
@@ -108,10 +125,10 @@ std::shared_ptr<minikin::MinikinFont> MinikinFontSkia::createFontWithVariation(
}
params.setAxes(skAxes.data(), skAxes.size());
sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
- sk_sp<SkTypeface> face(fm->createFromStream(stream, params));
+ sk_sp<SkTypeface> face(fm->makeFromStream(std::move(stream), params));
return std::make_shared<MinikinFontSkia>(std::move(face), mFontData, mFontSize, ttcIndex,
- variations);
+ variations);
}
uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
@@ -119,9 +136,9 @@ uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
SkPaint::Hinting hinting = paint->getHinting();
// select only flags that might affect text layout
flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
- SkPaint::kSubpixelText_Flag | SkPaint::kDevKernText_Flag |
- SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kAutoHinting_Flag |
- SkPaint::kVerticalText_Flag);
+ SkPaint::kSubpixelText_Flag | SkPaint::kDevKernText_Flag |
+ SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kAutoHinting_Flag |
+ SkPaint::kVerticalText_Flag);
flags |= (hinting << 16);
return flags;
}
@@ -132,12 +149,11 @@ void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
}
void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font,
- minikin::FontFakery fakery) {
+ minikin::FontFakery fakery) {
paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->RefSkTypeface());
paint->setFakeBoldText(paint->isFakeBoldText() || fakery.isFakeBold());
if (fakery.isFakeItalic()) {
paint->setTextSkewX(paint->getTextSkewX() - 0.25f);
}
}
-
}
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 6c12485845fd..d1565986304f 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -17,9 +17,9 @@
#ifndef _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
#define _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
+#include <SkRefCnt.h>
#include <cutils/compiler.h>
#include <minikin/MinikinFont.h>
-#include <SkRefCnt.h>
class SkPaint;
class SkTypeface;
@@ -29,13 +29,17 @@ namespace android {
class ANDROID_API MinikinFontSkia : public minikin::MinikinFont {
public:
explicit MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
- int ttcIndex, const std::vector<minikin::FontVariation>& axes);
+ int ttcIndex, const std::vector<minikin::FontVariation>& axes);
- float GetHorizontalAdvance(uint32_t glyph_id,
- const minikin::MinikinPaint &paint) const;
+ float GetHorizontalAdvance(uint32_t glyph_id, const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) const override;
void GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
- const minikin::MinikinPaint &paint) const;
+ const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) const override;
+
+ void GetFontExtent(minikin::MinikinExtent* extent, const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) const override;
SkTypeface* GetSkTypeface() const;
sk_sp<SkTypeface> RefSkTypeface() const;
@@ -53,7 +57,8 @@ public:
// set typeface and fake bold/italic parameters
static void populateSkPaint(SkPaint* paint, const minikin::MinikinFont* font,
- minikin::FontFakery fakery);
+ minikin::FontFakery fakery);
+
private:
sk_sp<SkTypeface> mTypeface;
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 415eef77f44e..5b69bb78101f 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -20,60 +20,69 @@
#include <log/log.h>
+#include <minikin/MeasuredText.h>
#include "Paint.h"
#include "SkPathMeasure.h"
#include "Typeface.h"
namespace android {
-minikin::FontStyle MinikinUtils::prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
- const Paint* paint, Typeface* typeface) {
+minikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint,
+ const Typeface* typeface) {
const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
- minikin::FontStyle resolved = resolvedFace->fStyle;
-
- /* Prepare minikin FontStyle */
- minikin::FontVariant minikinVariant = (paint->getFontVariant() == minikin::VARIANT_ELEGANT) ?
- minikin::VARIANT_ELEGANT : minikin::VARIANT_COMPACT;
- const uint32_t langListId = paint->getMinikinLangListId();
- minikin::FontStyle minikinStyle(langListId, minikinVariant, resolved.getWeight(),
- resolved.getItalic());
+ minikin::MinikinPaint minikinPaint(resolvedFace->fFontCollection);
/* Prepare minikin Paint */
- // Note: it would be nice to handle fractional size values (it would improve smooth zoom
- // behavior), but historically size has been treated as an int.
- // TODO: explore whether to enable fractional sizes, possibly when linear text flag is set.
- minikinPaint->size = (int)paint->getTextSize();
- minikinPaint->scaleX = paint->getTextScaleX();
- minikinPaint->skewX = paint->getTextSkewX();
- minikinPaint->letterSpacing = paint->getLetterSpacing();
- minikinPaint->wordSpacing = paint->getWordSpacing();
- minikinPaint->paintFlags = MinikinFontSkia::packPaintFlags(paint);
- minikinPaint->fontFeatureSettings = paint->getFontFeatureSettings();
- minikinPaint->hyphenEdit = minikin::HyphenEdit(paint->getHyphenEdit());
- return minikinStyle;
+ minikinPaint.size =
+ paint->isLinearText() ? paint->getTextSize() : static_cast<int>(paint->getTextSize());
+ minikinPaint.scaleX = paint->getTextScaleX();
+ minikinPaint.skewX = paint->getTextSkewX();
+ minikinPaint.letterSpacing = paint->getLetterSpacing();
+ minikinPaint.wordSpacing = paint->getWordSpacing();
+ minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint);
+ minikinPaint.localeListId = paint->getMinikinLocaleListId();
+ minikinPaint.familyVariant = paint->getFamilyVariant();
+ minikinPaint.fontStyle = resolvedFace->fStyle;
+ minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings();
+ return minikinPaint;
}
-minikin::Layout MinikinUtils::doLayout(const Paint* paint, int bidiFlags,
- Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
- size_t bufSize) {
- minikin::MinikinPaint minikinPaint;
- minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
+minikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFlags,
+ const Typeface* typeface, const uint16_t* buf, size_t start,
+ size_t count, size_t bufSize, minikin::MeasuredText* mt) {
+ minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
minikin::Layout layout;
- layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint,
- Typeface::resolveDefault(typeface)->fFontCollection);
+
+ const minikin::U16StringPiece textBuf(buf, bufSize);
+ const minikin::Range range(start, start + count);
+ const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit());
+ const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit);
+ const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit);
+
+ if (mt == nullptr) {
+ layout.doLayout(textBuf,range, bidiFlags, minikinPaint, startHyphen, endHyphen);
+ } else {
+ mt->buildLayout(textBuf, range, minikinPaint, bidiFlags, startHyphen, endHyphen, &layout);
+ }
return layout;
}
-float MinikinUtils::measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
- const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances) {
- minikin::MinikinPaint minikinPaint;
- minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
- Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
- return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle,
- minikinPaint, resolvedTypeface->fFontCollection, advances);
+float MinikinUtils::measureText(const Paint* paint, minikin::Bidi bidiFlags,
+ const Typeface* typeface, const uint16_t* buf, size_t start,
+ size_t count, size_t bufSize, float* advances) {
+ minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
+ const minikin::U16StringPiece textBuf(buf, bufSize);
+ const minikin::Range range(start, start + count);
+ const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit());
+ const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit);
+ const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit);
+
+ return minikin::Layout::measureText(textBuf, range, bidiFlags, minikinPaint, startHyphen,
+ endHyphen, advances, nullptr /* extent */,
+ nullptr /* layout pieces */);
}
-bool MinikinUtils::hasVariationSelector(Typeface* typeface, uint32_t codepoint, uint32_t vs) {
+bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) {
const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs);
}
@@ -93,7 +102,7 @@ float MinikinUtils::xOffsetForTextAlign(Paint* paint, const minikin::Layout& lay
}
float MinikinUtils::hOffsetForTextAlign(Paint* paint, const minikin::Layout& layout,
- const SkPath& path) {
+ const SkPath& path) {
float align = 0;
switch (paint->getTextAlign()) {
case Paint::kCenter_Align:
@@ -108,5 +117,4 @@ float MinikinUtils::hOffsetForTextAlign(Paint* paint, const minikin::Layout& lay
SkPathMeasure measure(path, false);
return align * (layout.getAdvance() - measure.getLength());
}
-
-}
+} // namespace android
diff --git a/libs/hwui/hwui/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h
index 0f22adc5d42b..77dfbb21f7b5 100644
--- a/libs/hwui/hwui/MinikinUtils.h
+++ b/libs/hwui/hwui/MinikinUtils.h
@@ -19,38 +19,46 @@
* Paint and so on.
**/
- // TODO: does this really need to be separate from MinikinSkia?
+// TODO: does this really need to be separate from MinikinSkia?
#ifndef _ANDROID_GRAPHICS_MINIKIN_UTILS_H_
#define _ANDROID_GRAPHICS_MINIKIN_UTILS_H_
#include <cutils/compiler.h>
#include <minikin/Layout.h>
-#include "Paint.h"
#include "MinikinSkia.h"
+#include "Paint.h"
#include "Typeface.h"
+#include <log/log.h>
+
+namespace minikin {
+class MeasuredText;
+} // namespace minikin
namespace android {
class MinikinUtils {
public:
- ANDROID_API static minikin::FontStyle prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
- const Paint* paint, Typeface* typeface);
+ ANDROID_API static minikin::MinikinPaint prepareMinikinPaint(const Paint* paint,
+ const Typeface* typeface);
- ANDROID_API static minikin::Layout doLayout(const Paint* paint, int bidiFlags,
- Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
- size_t bufSize);
+ ANDROID_API static minikin::Layout doLayout(const Paint* paint, minikin::Bidi bidiFlags,
+ const Typeface* typeface, const uint16_t* buf,
+ size_t start, size_t count, size_t bufSize,
+ minikin::MeasuredText* mt);
- ANDROID_API static float measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
- const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances);
+ ANDROID_API static float measureText(const Paint* paint, minikin::Bidi bidiFlags,
+ const Typeface* typeface, const uint16_t* buf,
+ size_t start, size_t count, size_t bufSize,
+ float* advances);
- ANDROID_API static bool hasVariationSelector(Typeface* typeface, uint32_t codepoint,
- uint32_t vs);
+ ANDROID_API static bool hasVariationSelector(const Typeface* typeface, uint32_t codepoint,
+ uint32_t vs);
ANDROID_API static float xOffsetForTextAlign(Paint* paint, const minikin::Layout& layout);
ANDROID_API static float hOffsetForTextAlign(Paint* paint, const minikin::Layout& layout,
- const SkPath& path);
+ const SkPath& path);
// f is a functor of type void f(size_t start, size_t end);
template <typename F>
ANDROID_API static void forFontRun(const minikin::Layout& layout, Paint* paint, F& f) {
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index a5d83a0ca018..002f75906c35 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GRAPHICS_PAINT_H_
#define ANDROID_GRAPHICS_PAINT_H_
+#include "Typeface.h"
+
#include <cutils/compiler.h>
#include <SkPaint.h>
@@ -30,8 +32,8 @@ class ANDROID_API Paint : public SkPaint {
public:
// Default values for underlined and strikethrough text,
// as defined by Skia in SkTextFormatParams.h.
- constexpr static float kStdStrikeThru_Offset = (-6.0f / 21.0f);
- constexpr static float kStdUnderline_Offset = (1.0f / 9.0f);
+ constexpr static float kStdStrikeThru_Offset = (-6.0f / 21.0f);
+ constexpr static float kStdUnderline_Offset = (1.0f / 9.0f);
constexpr static float kStdUnderline_Thickness = (1.0f / 18.0f);
constexpr static float kStdUnderline_Top =
@@ -49,67 +51,54 @@ public:
Paint& operator=(const Paint& other);
friend bool operator==(const Paint& a, const Paint& b);
- friend bool operator!=(const Paint& a, const Paint& b) {
- return !(a == b);
- }
+ friend bool operator!=(const Paint& a, const Paint& b) { return !(a == b); }
- void setLetterSpacing(float letterSpacing) {
- mLetterSpacing = letterSpacing;
- }
+ void setLetterSpacing(float letterSpacing) { mLetterSpacing = letterSpacing; }
- float getLetterSpacing() const {
- return mLetterSpacing;
- }
+ float getLetterSpacing() const { return mLetterSpacing; }
- void setWordSpacing(float wordSpacing) {
- mWordSpacing = wordSpacing;
- }
+ void setWordSpacing(float wordSpacing) { mWordSpacing = wordSpacing; }
- float getWordSpacing() const {
- return mWordSpacing;
- }
+ float getWordSpacing() const { return mWordSpacing; }
void setFontFeatureSettings(const std::string& fontFeatureSettings) {
mFontFeatureSettings = fontFeatureSettings;
}
- std::string getFontFeatureSettings() const {
- return mFontFeatureSettings;
- }
+ std::string getFontFeatureSettings() const { return mFontFeatureSettings; }
- void setMinikinLangListId(uint32_t minikinLangListId) {
- mMinikinLangListId = minikinLangListId;
+ void setMinikinLocaleListId(uint32_t minikinLocaleListId) {
+ mMinikinLocaleListId = minikinLocaleListId;
}
- uint32_t getMinikinLangListId() const {
- return mMinikinLangListId;
- }
+ uint32_t getMinikinLocaleListId() const { return mMinikinLocaleListId; }
- void setFontVariant(minikin::FontVariant variant) {
- mFontVariant = variant;
- }
+ void setFamilyVariant(minikin::FontFamily::Variant variant) { mFamilyVariant = variant; }
- minikin::FontVariant getFontVariant() const {
- return mFontVariant;
- }
+ minikin::FontFamily::Variant getFamilyVariant() const { return mFamilyVariant; }
- void setHyphenEdit(uint32_t hyphen) {
- mHyphenEdit = hyphen;
- }
+ void setHyphenEdit(uint32_t hyphen) { mHyphenEdit = hyphen; }
- uint32_t getHyphenEdit() const {
- return mHyphenEdit;
- }
+ uint32_t getHyphenEdit() const { return mHyphenEdit; }
+
+ void setAndroidTypeface(Typeface* typeface) { mTypeface = typeface; }
+
+ const Typeface* getAndroidTypeface() const { return mTypeface; }
private:
float mLetterSpacing = 0;
float mWordSpacing = 0;
std::string mFontFeatureSettings;
- uint32_t mMinikinLangListId;
- minikin::FontVariant mFontVariant;
+ uint32_t mMinikinLocaleListId;
+ minikin::FontFamily::Variant mFamilyVariant;
uint32_t mHyphenEdit = 0;
+ // The native Typeface object has the same lifetime of the Java Typeface
+ // object. The Java Paint object holds a strong reference to the Java Typeface
+ // object. Thus, following pointer can never be a dangling pointer. Note that
+ // nullptr is valid: it means the default typeface.
+ const Typeface* mTypeface = nullptr;
};
} // namespace android
-#endif // ANDROID_GRAPHICS_PAINT_H_
+#endif // ANDROID_GRAPHICS_PAINT_H_
diff --git a/libs/hwui/hwui/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp
index 67427433bb89..ae9c475d09d4 100644
--- a/libs/hwui/hwui/PaintImpl.cpp
+++ b/libs/hwui/hwui/PaintImpl.cpp
@@ -18,45 +18,52 @@
namespace android {
-Paint::Paint() :
- SkPaint(), mLetterSpacing(0), mWordSpacing(0), mFontFeatureSettings(),
- mMinikinLangListId(0), mFontVariant(minikin::VARIANT_DEFAULT) {
-}
+Paint::Paint()
+ : SkPaint()
+ , mLetterSpacing(0)
+ , mWordSpacing(0)
+ , mFontFeatureSettings()
+ , mMinikinLocaleListId(0)
+ , mFamilyVariant(minikin::FontFamily::Variant::DEFAULT) {}
-Paint::Paint(const Paint& paint) : SkPaint(paint),
- mLetterSpacing(paint.mLetterSpacing), mWordSpacing(paint.mWordSpacing),
- mFontFeatureSettings(paint.mFontFeatureSettings),
- mMinikinLangListId(paint.mMinikinLangListId), mFontVariant(paint.mFontVariant),
- mHyphenEdit(paint.mHyphenEdit) {
-}
+Paint::Paint(const Paint& paint)
+ : SkPaint(paint)
+ , mLetterSpacing(paint.mLetterSpacing)
+ , mWordSpacing(paint.mWordSpacing)
+ , mFontFeatureSettings(paint.mFontFeatureSettings)
+ , mMinikinLocaleListId(paint.mMinikinLocaleListId)
+ , mFamilyVariant(paint.mFamilyVariant)
+ , mHyphenEdit(paint.mHyphenEdit)
+ , mTypeface(paint.mTypeface) {}
-Paint::Paint(const SkPaint& paint) : SkPaint(paint),
- mLetterSpacing(0), mWordSpacing(0), mFontFeatureSettings(), mMinikinLangListId(0),
- mFontVariant(minikin::VARIANT_DEFAULT) {
-}
+Paint::Paint(const SkPaint& paint)
+ : SkPaint(paint)
+ , mLetterSpacing(0)
+ , mWordSpacing(0)
+ , mFontFeatureSettings()
+ , mMinikinLocaleListId(0)
+ , mFamilyVariant(minikin::FontFamily::Variant::DEFAULT) {}
-Paint::~Paint() {
-}
+Paint::~Paint() {}
Paint& Paint::operator=(const Paint& other) {
SkPaint::operator=(other);
mLetterSpacing = other.mLetterSpacing;
mWordSpacing = other.mWordSpacing;
mFontFeatureSettings = other.mFontFeatureSettings;
- mMinikinLangListId = other.mMinikinLangListId;
- mFontVariant = other.mFontVariant;
+ mMinikinLocaleListId = other.mMinikinLocaleListId;
+ mFamilyVariant = other.mFamilyVariant;
mHyphenEdit = other.mHyphenEdit;
+ mTypeface = other.mTypeface;
return *this;
}
bool operator==(const Paint& a, const Paint& b) {
- return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b)
- && a.mLetterSpacing == b.mLetterSpacing
- && a.mWordSpacing == b.mWordSpacing
- && a.mFontFeatureSettings == b.mFontFeatureSettings
- && a.mMinikinLangListId == b.mMinikinLangListId
- && a.mFontVariant == b.mFontVariant
- && a.mHyphenEdit == b.mHyphenEdit;
-}
-
+ return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b) &&
+ a.mLetterSpacing == b.mLetterSpacing && a.mWordSpacing == b.mWordSpacing &&
+ a.mFontFeatureSettings == b.mFontFeatureSettings &&
+ a.mMinikinLocaleListId == b.mMinikinLocaleListId &&
+ a.mFamilyVariant == b.mFamilyVariant && a.mHyphenEdit == b.mHyphenEdit &&
+ a.mTypeface == b.mTypeface;
}
+} // namespace android
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index f66bb045373c..dca9ef5559a6 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -14,23 +14,17 @@
* limitations under the License.
*/
-/**
- * This is the implementation of the Typeface object. Historically, it has
- * just been SkTypeface, but we are migrating to Minikin. For the time
- * being, that choice is hidden under the USE_MINIKIN compile-time flag.
- */
-
#include "Typeface.h"
-#include <pthread.h>
#include <fcntl.h> // For tests.
-#include <sys/stat.h> // For tests.
+#include <pthread.h>
#include <sys/mman.h> // For tests.
+#include <sys/stat.h> // For tests.
#include "MinikinSkia.h"
-#include "SkTypeface.h"
#include "SkPaint.h"
#include "SkStream.h" // Fot tests.
+#include "SkTypeface.h"
#include <minikin/FontCollection.h>
#include <minikin/FontFamily.h>
@@ -40,65 +34,64 @@
namespace android {
-static SkTypeface::Style computeSkiaStyle(int weight, bool italic) {
+static Typeface::Style computeAPIStyle(int weight, bool italic) {
// This bold detection comes from SkTypeface.h
if (weight >= SkFontStyle::kSemiBold_Weight) {
- return italic ? SkTypeface::kBoldItalic : SkTypeface::kBold;
+ return italic ? Typeface::kBoldItalic : Typeface::kBold;
} else {
- return italic ? SkTypeface::kItalic : SkTypeface::kNormal;
+ return italic ? Typeface::kItalic : Typeface::kNormal;
}
}
static minikin::FontStyle computeMinikinStyle(int weight, bool italic) {
- // TODO: Better to use raw base weight value for font selection instead of dividing by 100.
- const int minikinWeight = uirenderer::MathUtils::clamp((weight + 50) / 100, 1, 10);
- return minikin::FontStyle(minikinWeight, italic);
+ return minikin::FontStyle(uirenderer::MathUtils::clamp(weight, 1, 1000),
+ static_cast<minikin::FontStyle::Slant>(italic));
}
// Resolve the relative weight from the baseWeight and target style.
-static minikin::FontStyle computeRelativeStyle(int baseWeight, SkTypeface::Style relativeStyle) {
+static minikin::FontStyle computeRelativeStyle(int baseWeight, Typeface::Style relativeStyle) {
int weight = baseWeight;
- if ((relativeStyle & SkTypeface::kBold) != 0) {
+ if ((relativeStyle & Typeface::kBold) != 0) {
weight += 300;
}
- bool italic = (relativeStyle & SkTypeface::kItalic) != 0;
+ bool italic = (relativeStyle & Typeface::kItalic) != 0;
return computeMinikinStyle(weight, italic);
}
-Typeface* gDefaultTypeface = NULL;
+const Typeface* gDefaultTypeface = NULL;
-Typeface* Typeface::resolveDefault(Typeface* src) {
- LOG_ALWAYS_FATAL_IF(gDefaultTypeface == nullptr);
+const Typeface* Typeface::resolveDefault(const Typeface* src) {
+ LOG_ALWAYS_FATAL_IF(src == nullptr && gDefaultTypeface == nullptr);
return src == nullptr ? gDefaultTypeface : src;
}
-Typeface* Typeface::createRelative(Typeface* src, SkTypeface::Style style) {
- Typeface* resolvedFace = Typeface::resolveDefault(src);
+Typeface* Typeface::createRelative(Typeface* src, Typeface::Style style) {
+ const Typeface* resolvedFace = Typeface::resolveDefault(src);
Typeface* result = new Typeface;
if (result != nullptr) {
result->fFontCollection = resolvedFace->fFontCollection;
result->fBaseWeight = resolvedFace->fBaseWeight;
- result->fSkiaStyle = style;
+ result->fAPIStyle = style;
result->fStyle = computeRelativeStyle(result->fBaseWeight, style);
}
return result;
}
Typeface* Typeface::createAbsolute(Typeface* base, int weight, bool italic) {
- Typeface* resolvedFace = Typeface::resolveDefault(base);
+ const Typeface* resolvedFace = Typeface::resolveDefault(base);
Typeface* result = new Typeface();
if (result != nullptr) {
result->fFontCollection = resolvedFace->fFontCollection;
result->fBaseWeight = resolvedFace->fBaseWeight;
- result->fSkiaStyle = computeSkiaStyle(weight, italic);
+ result->fAPIStyle = computeAPIStyle(weight, italic);
result->fStyle = computeMinikinStyle(weight, italic);
}
return result;
}
-Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src,
- const std::vector<minikin::FontVariation>& variations) {
- Typeface* resolvedFace = Typeface::resolveDefault(src);
+Typeface* Typeface::createFromTypefaceWithVariation(
+ Typeface* src, const std::vector<minikin::FontVariation>& variations) {
+ const Typeface* resolvedFace = Typeface::resolveDefault(src);
Typeface* result = new Typeface();
if (result != nullptr) {
result->fFontCollection =
@@ -111,27 +104,26 @@ Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src,
// Do not update styles.
// TODO: We may want to update base weight if the 'wght' is specified.
result->fBaseWeight = resolvedFace->fBaseWeight;
- result->fSkiaStyle = resolvedFace->fSkiaStyle;
+ result->fAPIStyle = resolvedFace->fAPIStyle;
result->fStyle = resolvedFace->fStyle;
}
return result;
}
Typeface* Typeface::createWithDifferentBaseWeight(Typeface* src, int weight) {
- Typeface* resolvedFace = Typeface::resolveDefault(src);
+ const Typeface* resolvedFace = Typeface::resolveDefault(src);
Typeface* result = new Typeface;
if (result != nullptr) {
result->fFontCollection = resolvedFace->fFontCollection;
result->fBaseWeight = weight;
- result->fSkiaStyle = resolvedFace->fSkiaStyle;
- result->fStyle = computeRelativeStyle(weight, result->fSkiaStyle);
+ result->fAPIStyle = resolvedFace->fAPIStyle;
+ result->fStyle = computeRelativeStyle(weight, result->fAPIStyle);
}
return result;
}
-Typeface* Typeface::createFromFamilies(
- std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
- int weight, int italic) {
+Typeface* Typeface::createFromFamilies(std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
+ int weight, int italic) {
Typeface* result = new Typeface;
result->fFontCollection.reset(new minikin::FontCollection(families));
@@ -140,8 +132,8 @@ Typeface* Typeface::createFromFamilies(
bool italicFromFont;
const minikin::FontStyle defaultStyle;
- const minikin::MinikinFont* mf =
- families.empty() ? nullptr : families[0]->getClosestMatch(defaultStyle).font;
+ const minikin::MinikinFont* mf = families.empty() ? nullptr
+ : families[0]->getClosestMatch(defaultStyle).font->typeface().get();
if (mf != nullptr) {
SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
const SkFontStyle& style = skTypeface->fontStyle();
@@ -157,7 +149,7 @@ Typeface* Typeface::createFromFamilies(
weight = weightFromFont;
}
if (italic == RESOLVE_BY_FONT_TABLE) {
- italic = italicFromFont? 1 : 0;
+ italic = italicFromFont ? 1 : 0;
}
}
@@ -167,12 +159,12 @@ Typeface* Typeface::createFromFamilies(
}
result->fBaseWeight = weight;
- result->fSkiaStyle = computeSkiaStyle(weight, italic);
+ result->fAPIStyle = computeAPIStyle(weight, italic);
result->fStyle = computeMinikinStyle(weight, italic);
return result;
}
-void Typeface::setDefault(Typeface* face) {
+void Typeface::setDefault(const Typeface* face) {
gDefaultTypeface = face;
}
@@ -190,18 +182,18 @@ void Typeface::setRobotoTypefaceForTest() {
std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
- std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
- std::vector<minikin::Font>({ minikin::Font(std::move(font), minikin::FontStyle()) }));
- std::shared_ptr<minikin::FontCollection> collection =
- std::make_shared<minikin::FontCollection>(std::move(family));
+ std::vector<minikin::Font> fonts;
+ fonts.push_back(minikin::Font::Builder(font).build());
+
+ std::shared_ptr<minikin::FontCollection> collection = std::make_shared<minikin::FontCollection>(
+ std::make_shared<minikin::FontFamily>(std::move(fonts)));
Typeface* hwTypeface = new Typeface();
hwTypeface->fFontCollection = collection;
- hwTypeface->fSkiaStyle = SkTypeface::kNormal;
+ hwTypeface->fAPIStyle = Typeface::kNormal;
hwTypeface->fBaseWeight = SkFontStyle::kNormal_Weight;
- hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */);
+ hwTypeface->fStyle = minikin::FontStyle();
Typeface::setDefault(hwTypeface);
}
-
-}
+} // namespace android
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index db0b2cdeba00..ef8d8f4ee4f3 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
#ifndef _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
#define _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
@@ -22,8 +21,8 @@
#include <cutils/compiler.h>
#include <minikin/FontCollection.h>
-#include <vector>
#include <memory>
+#include <vector>
namespace android {
@@ -32,16 +31,17 @@ namespace android {
constexpr int RESOLVE_BY_FONT_TABLE = -1;
struct ANDROID_API Typeface {
- public:
+public:
std::shared_ptr<minikin::FontCollection> fFontCollection;
// resolved style actually used for rendering
minikin::FontStyle fStyle;
- // style used for constructing and querying Typeface objects
- SkTypeface::Style fSkiaStyle;
+ // style used in the API
+ enum Style : uint8_t { kNormal = 0, kBold = 0x01, kItalic = 0x02, kBoldItalic = 0x03 };
+ Style fAPIStyle;
- static Typeface* resolveDefault(Typeface* src);
+ static const Typeface* resolveDefault(const Typeface* src);
// The following three functions create new Typeface from an existing Typeface with a different
// style. There is a base weight concept which is used for calculating relative style from an
@@ -68,26 +68,24 @@ struct ANDROID_API Typeface {
//
// Typeface* black = createAbsolute(base, 900, false); // Rendered with a weight of 900.
static Typeface* createWithDifferentBaseWeight(Typeface* src, int baseweight);
- static Typeface* createRelative(Typeface* src, SkTypeface::Style desiredStyle);
+ static Typeface* createRelative(Typeface* src, Style desiredStyle);
static Typeface* createAbsolute(Typeface* base, int weight, bool italic);
- static Typeface* createFromTypefaceWithVariation(Typeface* src,
- const std::vector<minikin::FontVariation>& variations);
+ static Typeface* createFromTypefaceWithVariation(
+ Typeface* src, const std::vector<minikin::FontVariation>& variations);
static Typeface* createFromFamilies(
- std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
- int weight, int italic);
+ std::vector<std::shared_ptr<minikin::FontFamily>>&& families, int weight, int italic);
- static void setDefault(Typeface* face);
+ static void setDefault(const Typeface* face);
// Sets roboto font as the default typeface for testing purpose.
static void setRobotoTypefaceForTest();
- private:
+
+private:
// base weight in CSS-style units, 1..1000
int fBaseWeight;
-
};
-
}
#endif // _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
diff --git a/libs/hwui/pipeline/skia/AnimatedDrawables.h b/libs/hwui/pipeline/skia/AnimatedDrawables.h
index 44c494f77231..efef6de2a9e1 100644
--- a/libs/hwui/pipeline/skia/AnimatedDrawables.h
+++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h
@@ -16,10 +16,10 @@
#pragma once
-#include "CanvasProperty.h"
-#include <utils/RefBase.h>
#include <SkCanvas.h>
#include <SkDrawable.h>
+#include <utils/RefBase.h>
+#include "CanvasProperty.h"
namespace android {
namespace uirenderer {
@@ -28,16 +28,12 @@ namespace skiapipeline {
class AnimatedRoundRect : public SkDrawable {
public:
AnimatedRoundRect(uirenderer::CanvasPropertyPrimitive* left,
- uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
- uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
- uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* p)
- : mLeft(left)
- , mTop(top)
- , mRight(right)
- , mBottom(bottom)
- , mRx(rx)
- , mRy(ry)
- , mPaint(p) {}
+ uirenderer::CanvasPropertyPrimitive* top,
+ uirenderer::CanvasPropertyPrimitive* right,
+ uirenderer::CanvasPropertyPrimitive* bottom,
+ uirenderer::CanvasPropertyPrimitive* rx,
+ uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* p)
+ : mLeft(left), mTop(top), mRight(right), mBottom(bottom), mRx(rx), mRy(ry), mPaint(p) {}
protected:
virtual SkRect onGetBounds() override {
@@ -61,11 +57,9 @@ private:
class AnimatedCircle : public SkDrawable {
public:
AnimatedCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y,
- uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint)
- : mX(x)
- , mY(y)
- , mRadius(radius)
- , mPaint(paint) {}
+ uirenderer::CanvasPropertyPrimitive* radius,
+ uirenderer::CanvasPropertyPaint* paint)
+ : mX(x), mY(y), mRadius(radius), mPaint(paint) {}
protected:
virtual SkRect onGetBounds() override {
@@ -85,6 +79,6 @@ private:
sp<uirenderer::CanvasPropertyPaint> mPaint;
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/DumpOpsCanvas.h b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
index 34fb04ccad55..1f83d1a201b0 100644
--- a/libs/hwui/pipeline/skia/DumpOpsCanvas.h
+++ b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
@@ -16,6 +16,7 @@
#pragma once
+#include "RenderNode.h"
#include "SkiaDisplayList.h"
namespace android {
@@ -32,8 +33,7 @@ public:
: mOutput(output)
, mLevel(level)
, mDisplayList(displayList)
- , mIdent((level + 1) * 2, ' ') {
- }
+ , mIdent((level + 1) * 2, ' ') {}
protected:
void onClipRect(const SkRect& rect, SkClipOp, ClipEdgeStyle) override {
@@ -52,9 +52,7 @@ protected:
mOutput << mIdent << "clipRegion" << std::endl;
}
- void onDrawPaint(const SkPaint&) override {
- mOutput << mIdent << "drawPaint" << std::endl;
- }
+ void onDrawPaint(const SkPaint&) override { mOutput << mIdent << "drawPaint" << std::endl; }
void onDrawPath(const SkPath&, const SkPaint&) override {
mOutput << mIdent << "drawPath" << std::endl;
@@ -92,22 +90,21 @@ protected:
mOutput << mIdent << "drawPosText" << std::endl;
}
- void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar,
- const SkPaint&) override {
+ void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override {
mOutput << mIdent << "drawPosTextH" << std::endl;
}
void onDrawTextOnPath(const void*, size_t, const SkPath&, const SkMatrix*,
- const SkPaint&) override {
+ const SkPaint&) override {
mOutput << mIdent << "drawTextOnPath" << std::endl;
}
void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,
- const SkPaint&) override {
+ const SkPaint&) override {
mOutput << mIdent << "drawTextRSXform" << std::endl;
}
- void onDrawTextBlob(const SkTextBlob*, SkScalar,SkScalar, const SkPaint&) override {
+ void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override {
mOutput << mIdent << "drawTextBlob" << std::endl;
}
@@ -116,17 +113,17 @@ protected:
}
void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
- const SkPaint*) override {
+ const SkPaint*) override {
mOutput << mIdent << "drawImageNine" << std::endl;
}
void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
- SrcRectConstraint) override {
+ SrcRectConstraint) override {
mOutput << mIdent << "drawImageRect" << std::endl;
}
void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
- const SkPaint*) override {
+ const SkPaint*) override {
mOutput << mIdent << "drawImageLattice" << std::endl;
}
@@ -157,21 +154,21 @@ protected:
private:
RenderNodeDrawable* getRenderNodeDrawable(SkDrawable* drawable) {
- for (auto& child : mDisplayList.mChildNodes) {
+ for (auto& child : mDisplayList.mChildNodes) {
if (drawable == &child) {
return &child;
}
- }
- return nullptr;
+ }
+ return nullptr;
}
GLFunctorDrawable* getGLFunctorDrawable(SkDrawable* drawable) {
- for (auto& child : mDisplayList.mChildFunctors) {
+ for (auto& child : mDisplayList.mChildFunctors) {
if (drawable == &child) {
return &child;
}
- }
- return nullptr;
+ }
+ return nullptr;
}
std::ostream& mOutput;
@@ -180,6 +177,6 @@ private:
std::string mIdent;
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index ea302a154616..3684bc1e6a1f 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -15,18 +15,24 @@
*/
#include "GLFunctorDrawable.h"
+#include <GrContext.h>
+#include <private/hwui/DrawGlInfo.h>
#include "GlFunctorLifecycleListener.h"
#include "RenderNode.h"
+#include "SkAndroidFrameworkUtils.h"
#include "SkClipStack.h"
-#include <private/hwui/DrawGlInfo.h>
-#include <GrContext.h>
+#include "SkRect.h"
+#include "GrBackendSurface.h"
+#include "GrRenderTarget.h"
+#include "GrRenderTargetContext.h"
+#include "GrGLTypes.h"
namespace android {
namespace uirenderer {
namespace skiapipeline {
GLFunctorDrawable::~GLFunctorDrawable() {
- if(mListener.get() != nullptr) {
+ if (mListener.get() != nullptr) {
mListener->onGlFunctorReleased(mFunctor);
}
}
@@ -43,58 +49,143 @@ static void setScissor(int viewportHeight, const SkIRect& clip) {
glScissor(clip.fLeft, y, clip.width(), height);
}
+static bool GetFboDetails(SkCanvas* canvas, GLuint* outFboID, SkISize* outFboSize) {
+ GrRenderTargetContext *renderTargetContext =
+ canvas->internal_private_accessTopLayerRenderTargetContext();
+ if (!renderTargetContext) {
+ ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
+ return false;
+ }
+
+ GrRenderTarget *renderTarget = renderTargetContext->accessRenderTarget();
+ if (!renderTarget) {
+ ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
+ return false;
+ }
+
+ GrBackendRenderTarget backendTarget = renderTarget->getBackendRenderTarget();
+ const GrGLFramebufferInfo* fboInfo = backendTarget.getGLFramebufferInfo();
+
+ if (!fboInfo) {
+ ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
+ return false;
+ }
+
+ *outFboID = fboInfo->fFBOID;
+ *outFboSize = SkISize::Make(renderTargetContext->width(), renderTargetContext->height());
+ return true;
+}
+
void GLFunctorDrawable::onDraw(SkCanvas* canvas) {
if (canvas->getGrContext() == nullptr) {
SkDEBUGF(("Attempting to draw GLFunctor into an unsupported surface"));
return;
}
- canvas->flush();
-
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
canvas->clear(SK_ColorRED);
return;
}
- SkImageInfo canvasInfo = canvas->imageInfo();
+ GLuint fboID = 0;
+ SkISize fboSize;
+ if (!GetFboDetails(canvas, &fboID, &fboSize)) {
+ return;
+ }
+
+ SkIRect surfaceBounds = canvas->internal_private_getTopLayerBounds();
+ SkIRect clipBounds = canvas->getDeviceClipBounds();
SkMatrix44 mat4(canvas->getTotalMatrix());
+ SkRegion clipRegion;
+ canvas->temporary_internal_getRgnClip(&clipRegion);
- SkIRect ibounds = canvas->getDeviceClipBounds();
+ sk_sp<SkSurface> tmpSurface;
+ // we are in a state where there is an unclipped saveLayer
+ if (fboID != 0 && !surfaceBounds.contains(clipBounds)) {
+
+ // create an offscreen layer and clear it
+ SkImageInfo surfaceInfo = canvas->imageInfo().makeWH(clipBounds.width(), clipBounds.height());
+ tmpSurface = SkSurface::MakeRenderTarget(canvas->getGrContext(), SkBudgeted::kYes,
+ surfaceInfo);
+ tmpSurface->getCanvas()->clear(SK_ColorTRANSPARENT);
+
+ GrBackendObject backendObject;
+ if (!tmpSurface->getRenderTargetHandle(&backendObject, SkSurface::kFlushWrite_BackendHandleAccess)) {
+ ALOGW("Unable to extract renderTarget info from offscreen canvas; aborting GLFunctor");
+ return;
+ }
+
+ fboSize = SkISize::Make(surfaceInfo.width(), surfaceInfo.height());
+ fboID = (GLuint)backendObject;
+
+ // update the matrix and clip that we pass to the WebView to match the coordinates of
+ // the offscreen layer
+ mat4.preTranslate(-clipBounds.fLeft, -clipBounds.fTop, 0);
+ clipBounds.offsetTo(0, 0);
+ clipRegion.translate(-surfaceBounds.fLeft, -surfaceBounds.fTop);
+
+ } else if (fboID != 0) {
+ // we are drawing into a (clipped) offscreen layer so we must update the clip and matrix
+ // from device coordinates to the layer's coordinates
+ clipBounds.offset(-surfaceBounds.fLeft, -surfaceBounds.fTop);
+ mat4.preTranslate(-surfaceBounds.fLeft, -surfaceBounds.fTop, 0);
+ }
DrawGlInfo info;
- info.clipLeft = ibounds.fLeft;
- info.clipTop = ibounds.fTop;
- info.clipRight = ibounds.fRight;
- info.clipBottom = ibounds.fBottom;
- // info.isLayer = hasLayer();
- info.isLayer = false;
- info.width = canvasInfo.width();
- info.height = canvasInfo.height();
+ info.clipLeft = clipBounds.fLeft;
+ info.clipTop = clipBounds.fTop;
+ info.clipRight = clipBounds.fRight;
+ info.clipBottom = clipBounds.fBottom;
+ info.isLayer = fboID != 0;
+ info.width = fboSize.width();
+ info.height = fboSize.height();
mat4.asColMajorf(&info.transform[0]);
- //apply a simple clip with a scissor or a complex clip with a stencil
- SkRegion clipRegion;
- canvas->temporary_internal_getRgnClip(&clipRegion);
+ // ensure that the framebuffer that the webview will render into is bound before we clear
+ // the stencil and/or draw the functor.
+ canvas->flush();
+ glViewport(0, 0, info.width, info.height);
+ glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+
+ // apply a simple clip with a scissor or a complex clip with a stencil
+ bool clearStencilAfterFunctor = false;
if (CC_UNLIKELY(clipRegion.isComplex())) {
- //It is only a temporary solution to use a scissor to draw the stencil.
- //There is a bug 31489986 to implement efficiently non-rectangular clips.
+ // clear the stencil
+ //TODO: move stencil clear and canvas flush to SkAndroidFrameworkUtils::clipWithStencil
glDisable(GL_SCISSOR_TEST);
- glDisable(GL_STENCIL_TEST);
- glStencilMask(0xff);
+ glStencilMask(0x1);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
- glEnable(GL_SCISSOR_TEST);
- SkRegion::Cliperator it(clipRegion, ibounds);
- while (!it.done()) {
- setScissor(info.height, it.rect());
- glClearStencil(0x1);
- glClear(GL_STENCIL_BUFFER_BIT);
- it.next();
+
+ // notify Skia that we just updated the FBO and stencil
+ const uint32_t grState = kStencil_GrGLBackendState | kRenderTarget_GrGLBackendState;
+ canvas->getGrContext()->resetContext(grState);
+
+ SkCanvas* tmpCanvas = canvas;
+ if (tmpSurface) {
+ tmpCanvas = tmpSurface->getCanvas();
+ // set the clip on the new canvas
+ tmpCanvas->clipRegion(clipRegion);
+ }
+
+ // GL ops get inserted here if previous flush is missing, which could dirty the stencil
+ bool stencilWritten = SkAndroidFrameworkUtils::clipWithStencil(tmpCanvas);
+ tmpCanvas->flush(); //need this flush for the single op that draws into the stencil
+
+ // ensure that the framebuffer that the webview will render into is bound before after we
+ // draw into the stencil
+ glViewport(0, 0, info.width, info.height);
+ glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+
+ if (stencilWritten) {
+ glStencilMask(0x1);
+ glStencilFunc(GL_EQUAL, 0x1, 0x1);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ clearStencilAfterFunctor = true;
+ glEnable(GL_STENCIL_TEST);
+ } else {
+ glDisable(GL_STENCIL_TEST);
}
- glDisable(GL_SCISSOR_TEST);
- glStencilFunc(GL_EQUAL, 0x1, 0xff);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glEnable(GL_STENCIL_TEST);
} else if (clipRegion.isEmpty()) {
glDisable(GL_STENCIL_TEST);
glDisable(GL_SCISSOR_TEST);
@@ -106,9 +197,32 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) {
(*mFunctor)(DrawGlInfo::kModeDraw, &info);
+ if (clearStencilAfterFunctor) {
+ // clear stencil buffer as it may be used by Skia
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glStencilMask(0x1);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ }
+
canvas->getGrContext()->resetContext();
- }
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+ // if there were unclipped save layers involved we draw our offscreen surface to the canvas
+ if (tmpSurface) {
+ SkAutoCanvasRestore acr(canvas, true);
+ SkMatrix invertedMatrix;
+ if (!canvas->getTotalMatrix().invert(&invertedMatrix)) {
+ ALOGW("Unable to extract invert canvas matrix; aborting GLFunctor draw");
+ return;
+ }
+ canvas->concat(invertedMatrix);
+
+ const SkIRect deviceBounds = canvas->getDeviceClipBounds();
+ tmpSurface->draw(canvas, deviceBounds.fLeft, deviceBounds.fTop, nullptr);
+ }
+}
+
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.h b/libs/hwui/pipeline/skia/GLFunctorDrawable.h
index 012c948be9b3..af57d7d33c2c 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.h
@@ -19,8 +19,8 @@
#include <SkCanvas.h>
#include <SkDrawable.h>
-#include <utils/RefBase.h>
#include <utils/Functor.h>
+#include <utils/RefBase.h>
namespace android {
namespace uirenderer {
@@ -36,24 +36,21 @@ namespace skiapipeline {
class GLFunctorDrawable : public SkDrawable {
public:
GLFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener, SkCanvas* canvas)
- : mFunctor(functor)
- , mListener(listener)
- , mBounds(canvas->getLocalClipBounds())
- {}
+ : mFunctor(functor), mListener(listener), mBounds(canvas->getLocalClipBounds()) {}
virtual ~GLFunctorDrawable();
void syncFunctor() const;
- protected:
+protected:
virtual SkRect onGetBounds() override { return mBounds; }
virtual void onDraw(SkCanvas* canvas) override;
- private:
- Functor* mFunctor;
- sp<GlFunctorLifecycleListener> mListener;
- const SkRect mBounds;
+private:
+ Functor* mFunctor;
+ sp<GlFunctorLifecycleListener> mListener;
+ const SkRect mBounds;
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 4feeb2d6facb..4f16ddb9881b 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "GlLayer.h"
#include "LayerDrawable.h"
+#include "GlLayer.h"
#include "VkLayer.h"
#include "GrBackendSurface.h"
@@ -28,29 +28,38 @@ namespace uirenderer {
namespace skiapipeline {
void LayerDrawable::onDraw(SkCanvas* canvas) {
- DrawLayer(canvas->getGrContext(), canvas, mLayer.get());
+ Layer* layer = mLayerUpdater->backingLayer();
+ if (layer) {
+ DrawLayer(canvas->getGrContext(), canvas, layer);
+ }
}
-bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer) {
- // transform the matrix based on the layer
- int saveCount = -1;
- if (!layer->getTransform().isIdentity()) {
- saveCount = canvas->save();
- SkMatrix transform;
- layer->getTransform().copyTo(transform);
- canvas->concat(transform);
+bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
+ const SkRect* dstRect) {
+ if (context == nullptr) {
+ SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
+ return false;
}
-
+ // transform the matrix based on the layer
+ SkMatrix layerTransform;
+ layer->getTransform().copyTo(layerTransform);
sk_sp<SkImage> layerImage;
+ const int layerWidth = layer->getWidth();
+ const int layerHeight = layer->getHeight();
if (layer->getApi() == Layer::Api::OpenGL) {
GlLayer* glLayer = static_cast<GlLayer*>(layer);
GrGLTextureInfo externalTexture;
externalTexture.fTarget = glLayer->getRenderTarget();
externalTexture.fID = glLayer->getTextureId();
- GrBackendTexture backendTexture(glLayer->getWidth(), glLayer->getHeight(),
- kRGBA_8888_GrPixelConfig, externalTexture);
+ // The format may not be GL_RGBA8, but given the DeferredLayerUpdater and GLConsumer don't
+ // expose that info we use it as our default. Further, given that we only use this texture
+ // as a source this will not impact how Skia uses the texture. The only potential affect
+ // this is anticipated to have is that for some format types if we are not bound as an OES
+ // texture we may get invalid results for SKP capture if we read back the texture.
+ externalTexture.fFormat = GL_RGBA8;
+ GrBackendTexture backendTexture(layerWidth, layerHeight, GrMipMapped::kNo, externalTexture);
layerImage = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
- kPremul_SkAlphaType, nullptr);
+ kPremul_SkAlphaType, nullptr);
} else {
SkASSERT(layer->getApi() == Layer::Api::Vulkan);
VkLayer* vkLayer = static_cast<VkLayer*>(layer);
@@ -59,20 +68,55 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer
}
if (layerImage) {
+ SkMatrix textureMatrixInv;
+ layer->getTexTransform().copyTo(textureMatrixInv);
+ // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
+ // use bottom left origin and remove flipV and invert transformations.
+ SkMatrix flipV;
+ flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
+ textureMatrixInv.preConcat(flipV);
+ textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight);
+ textureMatrixInv.postScale(layerWidth, layerHeight);
+ SkMatrix textureMatrix;
+ if (!textureMatrixInv.invert(&textureMatrix)) {
+ textureMatrix = textureMatrixInv;
+ }
+
+ SkMatrix matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+
SkPaint paint;
paint.setAlpha(layer->getAlpha());
paint.setBlendMode(layer->getMode());
- paint.setColorFilter(sk_ref_sp(layer->getColorFilter()));
- canvas->drawImage(layerImage, 0, 0, &paint);
- }
- // restore the original matrix
- if (saveCount >= 0) {
- canvas->restoreToCount(saveCount);
+ paint.setColorFilter(layer->getColorSpaceWithFilter());
+
+ const bool nonIdentityMatrix = !matrix.isIdentity();
+ if (nonIdentityMatrix) {
+ canvas->save();
+ canvas->concat(matrix);
+ }
+ if (dstRect) {
+ SkMatrix matrixInv;
+ if (!matrix.invert(&matrixInv)) {
+ matrixInv = matrix;
+ }
+ SkRect srcRect = SkRect::MakeIWH(layerWidth, layerHeight);
+ matrixInv.mapRect(&srcRect);
+ SkRect skiaDestRect = *dstRect;
+ matrixInv.mapRect(&skiaDestRect);
+ canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint,
+ SkCanvas::kFast_SrcRectConstraint);
+ } else {
+ canvas->drawImage(layerImage.get(), 0, 0, &paint);
+ }
+ // restore the original matrix
+ if (nonIdentityMatrix) {
+ canvas->restore();
+ }
}
return layerImage;
}
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.h b/libs/hwui/pipeline/skia/LayerDrawable.h
index 431989519a70..18d118405a39 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.h
+++ b/libs/hwui/pipeline/skia/LayerDrawable.h
@@ -16,7 +16,7 @@
#pragma once
-#include "Layer.h"
+#include "DeferredLayerUpdater.h"
#include <SkCanvas.h>
#include <SkDrawable.h>
@@ -29,21 +29,22 @@ namespace skiapipeline {
* Draws a layer backed by an OpenGL texture into a SkCanvas.
*/
class LayerDrawable : public SkDrawable {
- public:
- explicit LayerDrawable(Layer* layer)
- : mLayer(layer) {}
+public:
+ explicit LayerDrawable(DeferredLayerUpdater* layerUpdater) : mLayerUpdater(layerUpdater) {}
- static bool DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer);
- protected:
- virtual SkRect onGetBounds() override {
- return SkRect::MakeWH(mLayer->getWidth(), mLayer->getHeight());
- }
- virtual void onDraw(SkCanvas* canvas) override;
+ static bool DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
+ const SkRect* dstRect = nullptr);
+
+protected:
+ virtual SkRect onGetBounds() override {
+ return SkRect::MakeWH(mLayerUpdater->getWidth(), mLayerUpdater->getHeight());
+ }
+ virtual void onDraw(SkCanvas* canvas) override;
private:
- sp<Layer> mLayer;
+ sp<DeferredLayerUpdater> mLayerUpdater;
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 4ee47afe87fd..6c04d7862979 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -15,6 +15,7 @@
*/
#include "RenderNodeDrawable.h"
+#include <SkPaintFilterCanvas.h>
#include "RenderNode.h"
#include "SkiaDisplayList.h"
#include "SkiaPipeline.h"
@@ -24,23 +25,24 @@ namespace android {
namespace uirenderer {
namespace skiapipeline {
-void RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas, const SkiaDisplayList& displayList,
- int nestLevel) {
+void RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas,
+ const SkiaDisplayList& displayList,
+ int nestLevel) {
LOG_ALWAYS_FATAL_IF(0 == nestLevel && !displayList.mProjectionReceiver);
for (auto& child : displayList.mChildNodes) {
const RenderProperties& childProperties = child.getNodeProperties();
- //immediate children cannot be projected on their parent
+ // immediate children cannot be projected on their parent
if (childProperties.getProjectBackwards() && nestLevel > 0) {
SkAutoCanvasRestore acr2(canvas, true);
- //Apply recorded matrix, which is a total matrix saved at recording time to avoid
- //replaying all DL commands.
+ // Apply recorded matrix, which is a total matrix saved at recording time to avoid
+ // replaying all DL commands.
canvas->concat(child.getRecordedMatrix());
child.drawContent(canvas);
}
- //skip walking sub-nodes if current display list contains a receiver with exception of
- //level 0, which is a known receiver
+ // skip walking sub-nodes if current display list contains a receiver with exception of
+ // level 0, which is a known receiver
if (0 == nestLevel || !displayList.containsProjectionReceiver()) {
SkAutoCanvasRestore acr(canvas, true);
SkMatrix nodeMatrix;
@@ -50,9 +52,9 @@ void RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas, const Ski
hwuiMatrix.copyTo(nodeMatrix);
canvas->concat(nodeMatrix);
SkiaDisplayList* childDisplayList = static_cast<SkiaDisplayList*>(
- (const_cast<DisplayList*>(childNode->getDisplayList())));
+ (const_cast<DisplayList*>(childNode->getDisplayList())));
if (childDisplayList) {
- drawBackwardsProjectedNodes(canvas, *childDisplayList, nestLevel+1);
+ drawBackwardsProjectedNodes(canvas, *childDisplayList, nestLevel + 1);
}
}
}
@@ -91,8 +93,8 @@ const RenderProperties& RenderNodeDrawable::getNodeProperties() const {
}
void RenderNodeDrawable::onDraw(SkCanvas* canvas) {
- //negative and positive Z order are drawn out of order, if this render node drawable is in
- //a reordering section
+ // negative and positive Z order are drawn out of order, if this render node drawable is in
+ // a reordering section
if ((!mInReorderingSection) || MathUtils::isZero(mRenderNode->properties().getZ())) {
this->forceDraw(canvas);
}
@@ -100,7 +102,7 @@ void RenderNodeDrawable::onDraw(SkCanvas* canvas) {
void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
RenderNode* renderNode = mRenderNode.get();
- if (SkiaPipeline::skpCaptureEnabled()) {
+ if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight());
canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr);
}
@@ -108,7 +110,8 @@ void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
// We only respect the nothingToDraw check when we are composing a layer. This
// ensures that we paint the layer even if it is not currently visible in the
// event that the properties change and it becomes visible.
- if (!renderNode->isRenderable() || (renderNode->nothingToDraw() && mComposeLayer)) {
+ if ((mProjectedDisplayList == nullptr && !renderNode->isRenderable()) ||
+ (renderNode->nothingToDraw() && mComposeLayer)) {
return;
}
@@ -117,13 +120,13 @@ void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
SkAutoCanvasRestore acr(canvas, true);
const RenderProperties& properties = this->getNodeProperties();
- //pass this outline to the children that may clip backward projected nodes
- displayList->mProjectedOutline = displayList->containsProjectionReceiver()
- ? &properties.getOutline() : nullptr;
+ // pass this outline to the children that may clip backward projected nodes
+ displayList->mProjectedOutline =
+ displayList->containsProjectionReceiver() ? &properties.getOutline() : nullptr;
if (!properties.getProjectBackwards()) {
drawContent(canvas);
if (mProjectedDisplayList) {
- acr.restore(); //draw projected children using parent matrix
+ acr.restore(); // draw projected children using parent matrix
LOG_ALWAYS_FATAL_IF(!mProjectedDisplayList->mProjectedOutline);
const bool shouldClip = mProjectedDisplayList->mProjectedOutline->getPath();
SkAutoCanvasRestore acr2(canvas, shouldClip);
@@ -137,12 +140,11 @@ void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
displayList->mProjectedOutline = nullptr;
}
-static bool layerNeedsPaint(const LayerProperties& properties,
- float alphaMultiplier, SkPaint* paint) {
- if (alphaMultiplier < 1.0f
- || properties.alpha() < 255
- || properties.xferMode() != SkBlendMode::kSrcOver
- || properties.colorFilter() != nullptr) {
+static bool layerNeedsPaint(const LayerProperties& properties, float alphaMultiplier,
+ SkPaint* paint) {
+ paint->setFilterQuality(kLow_SkFilterQuality);
+ if (alphaMultiplier < 1.0f || properties.alpha() < 255 ||
+ properties.xferMode() != SkBlendMode::kSrcOver || properties.colorFilter() != nullptr) {
paint->setAlpha(properties.alpha() * alphaMultiplier);
paint->setBlendMode(properties.xferMode());
paint->setColorFilter(sk_ref_sp(properties.colorFilter()));
@@ -151,6 +153,29 @@ static bool layerNeedsPaint(const LayerProperties& properties,
return false;
}
+class AlphaFilterCanvas : public SkPaintFilterCanvas {
+public:
+ AlphaFilterCanvas(SkCanvas* canvas, float alpha) : SkPaintFilterCanvas(canvas), mAlpha(alpha) {}
+
+protected:
+ bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type t) const override {
+ SkTLazy<SkPaint> defaultPaint;
+ if (!*paint) {
+ paint->init(*defaultPaint.init());
+ }
+ paint->writable()->setAlpha((uint8_t)(*paint)->getAlpha() * mAlpha);
+ return true;
+ }
+ void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
+ // We unroll the drawable using "this" canvas, so that draw calls contained inside will
+ // get their alpha applied. THe default SkPaintFilterCanvas::onDrawDrawable does not unroll.
+ drawable->draw(this, matrix);
+ }
+
+private:
+ float mAlpha;
+};
+
void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
RenderNode* renderNode = mRenderNode.get();
float alphaMultiplier = 1.0f;
@@ -167,7 +192,7 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
displayList->mProjectedReceiverParentMatrix = canvas->getTotalMatrix();
}
- //TODO should we let the bound of the drawable do this for us?
+ // TODO should we let the bound of the drawable do this for us?
const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
bool quickRejected = properties.getClipToBounds() && canvas->quickReject(bounds);
if (!quickRejected) {
@@ -176,12 +201,15 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
// composing a hardware layer
if (renderNode->getLayerSurface() && mComposeLayer) {
SkASSERT(properties.effectiveLayerType() == LayerType::RenderLayer);
- SkPaint* paint = nullptr;
- SkPaint tmpPaint;
- if (layerNeedsPaint(layerProperties, alphaMultiplier, &tmpPaint)) {
- paint = &tmpPaint;
- }
- renderNode->getLayerSurface()->draw(canvas, 0, 0, paint);
+ SkPaint paint;
+ layerNeedsPaint(layerProperties, alphaMultiplier, &paint);
+
+ // surfaces for layers are created on LAYER_SIZE boundaries (which are >= layer size) so
+ // we need to restrict the portion of the surface drawn to the size of the renderNode.
+ SkASSERT(renderNode->getLayerSurface()->width() >= bounds.width());
+ SkASSERT(renderNode->getLayerSurface()->height() >= bounds.height());
+ canvas->drawImageRect(renderNode->getLayerSurface()->makeImageSnapshot().get(),
+ bounds, bounds, &paint);
if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) {
renderNode->getSkiaLayer()->hasRenderedSinceRepaint = true;
@@ -198,26 +226,21 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
canvas->drawRect(bounds, transparentPaint);
}
}
-
- // composing a software layer with alpha
- } else if (properties.effectiveLayerType() == LayerType::Software) {
- SkPaint paint;
- bool needsLayer = layerNeedsPaint(layerProperties, alphaMultiplier, &paint);
- if (needsLayer) {
- canvas->saveLayer(bounds, &paint);
- }
- displayList->draw(canvas);
- if (needsLayer) {
- canvas->restore();
- }
} else {
- displayList->draw(canvas);
+ if (alphaMultiplier < 1.0f) {
+ // Non-layer draw for a view with getHasOverlappingRendering=false, will apply
+ // the alpha to the paint of each nested draw.
+ AlphaFilterCanvas alphaCanvas(canvas, alphaMultiplier);
+ displayList->draw(&alphaCanvas);
+ } else {
+ displayList->draw(canvas);
+ }
}
}
}
void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, SkCanvas* canvas,
- float* alphaMultiplier) {
+ float* alphaMultiplier) {
if (properties.getLeft() != 0 || properties.getTop() != 0) {
canvas->translate(properties.getLeft(), properties.getTop());
}
@@ -237,7 +260,7 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S
int clipFlags = properties.getClippingFlags();
if (properties.getAlpha() < 1) {
if (isLayer) {
- clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
+ clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
}
if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) {
*alphaMultiplier = properties.getAlpha();
@@ -246,18 +269,18 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S
Rect layerBounds(0, 0, properties.getWidth(), properties.getHeight());
if (clipFlags) {
properties.getClippingRectForFlags(clipFlags, &layerBounds);
- clipFlags = 0; // all clipping done by savelayer
+ clipFlags = 0; // all clipping done by savelayer
}
- SkRect bounds = SkRect::MakeLTRB(layerBounds.left, layerBounds.top,
- layerBounds.right, layerBounds.bottom);
- canvas->saveLayerAlpha(&bounds, (int) (properties.getAlpha() * 255));
+ SkRect bounds = SkRect::MakeLTRB(layerBounds.left, layerBounds.top, layerBounds.right,
+ layerBounds.bottom);
+ canvas->saveLayerAlpha(&bounds, (int)(properties.getAlpha() * 255));
}
if (CC_UNLIKELY(ATRACE_ENABLED() && properties.promotedToLayer())) {
// pretend alpha always causes savelayer to warn about
// performance problem affecting old versions
ATRACE_FORMAT("alpha caused saveLayer %dx%d", properties.getWidth(),
- properties.getHeight());
+ properties.getHeight());
}
}
@@ -283,6 +306,6 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S
}
}
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.h b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
index 3eed6476c994..ef21cd8a29b5 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.h
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
@@ -47,7 +47,7 @@ public:
* layer into the canvas.
*/
explicit RenderNodeDrawable(RenderNode* node, SkCanvas* canvas, bool composeLayer = true,
- bool inReorderingSection = false)
+ bool inReorderingSection = false)
: mRenderNode(node)
, mRecordedTransform(canvas->getTotalMatrix())
, mComposeLayer(composeLayer)
@@ -113,13 +113,13 @@ private:
* @param nestLevel should be always 0. Used to track how far we are from the receiver.
*/
void drawBackwardsProjectedNodes(SkCanvas* canvas, const SkiaDisplayList& displayList,
- int nestLevel = 0);
+ int nestLevel = 0);
/**
* Applies the rendering properties of a view onto a SkCanvas.
*/
static void setViewProperties(const RenderProperties& properties, SkCanvas* canvas,
- float* alphaMultiplier);
+ float* alphaMultiplier);
/**
* Stores transform on the canvas at time of recording and is used for
@@ -150,6 +150,6 @@ private:
SkiaDisplayList* mProjectedDisplayList = nullptr;
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 374d364787de..25c51f2716e6 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -30,26 +30,24 @@ namespace uirenderer {
namespace skiapipeline {
StartReorderBarrierDrawable::StartReorderBarrierDrawable(SkiaDisplayList* data)
- : mEndChildIndex(0)
- , mBeginChildIndex(data->mChildNodes.size())
- , mDisplayList(data) {
-}
+ : mEndChildIndex(0), mBeginChildIndex(data->mChildNodes.size()), mDisplayList(data) {}
void StartReorderBarrierDrawable::onDraw(SkCanvas* canvas) {
if (mChildren.empty()) {
- //mChildren is allocated and initialized only the first time onDraw is called and cached for
- //subsequent calls
+ // mChildren is allocated and initialized only the first time onDraw is called and cached
+ // for
+ // subsequent calls
mChildren.reserve(mEndChildIndex - mBeginChildIndex + 1);
for (int i = mBeginChildIndex; i <= mEndChildIndex; i++) {
mChildren.push_back(const_cast<RenderNodeDrawable*>(&mDisplayList->mChildNodes[i]));
}
}
std::stable_sort(mChildren.begin(), mChildren.end(),
- [](RenderNodeDrawable* a, RenderNodeDrawable* b) {
- const float aZValue = a->getNodeProperties().getZ();
- const float bZValue = b->getNodeProperties().getZ();
- return aZValue < bZValue;
- });
+ [](RenderNodeDrawable* a, RenderNodeDrawable* b) {
+ const float aZValue = a->getNodeProperties().getZ();
+ const float bZValue = b->getNodeProperties().getZ();
+ return aZValue < bZValue;
+ });
size_t drawIndex = 0;
const size_t endIndex = mChildren.size();
@@ -57,7 +55,7 @@ void StartReorderBarrierDrawable::onDraw(SkCanvas* canvas) {
RenderNodeDrawable* childNode = mChildren[drawIndex];
SkASSERT(childNode);
const float casterZ = childNode->getNodeProperties().getZ();
- if (casterZ >= -NON_ZERO_EPSILON) { //draw only children with negative Z
+ if (casterZ >= -NON_ZERO_EPSILON) { // draw only children with negative Z
return;
}
childNode->forceDraw(canvas);
@@ -85,8 +83,9 @@ void EndReorderBarrierDrawable::onDraw(SkCanvas* canvas) {
size_t drawIndex = 0;
const size_t endIndex = zChildren.size();
- while (drawIndex < endIndex //draw only children with positive Z
- && zChildren[drawIndex]->getNodeProperties().getZ() <= NON_ZERO_EPSILON) drawIndex++;
+ while (drawIndex < endIndex // draw only children with positive Z
+ && zChildren[drawIndex]->getNodeProperties().getZ() <= NON_ZERO_EPSILON)
+ drawIndex++;
size_t shadowIndex = drawIndex;
float lastCasterZ = 0.0f;
@@ -98,7 +97,7 @@ void EndReorderBarrierDrawable::onDraw(SkCanvas* canvas) {
// OR if its caster's Z value is similar to the previous potential caster
if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
this->drawShadow(canvas, zChildren[shadowIndex]);
- lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
+ lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
shadowIndex++;
continue;
}
@@ -112,27 +111,29 @@ void EndReorderBarrierDrawable::onDraw(SkCanvas* canvas) {
}
}
+static SkColor multiplyAlpha(SkColor color, float alpha) {
+ return SkColorSetA(color, alpha * SkColorGetA(color));
+}
+
// copied from FrameBuilder::deferShadow
void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) {
const RenderProperties& casterProperties = caster->getNodeProperties();
- if (casterProperties.getAlpha() <= 0.0f
- || casterProperties.getOutline().getAlpha() <= 0.0f
- || !casterProperties.getOutline().getPath()
- || casterProperties.getScaleX() == 0
- || casterProperties.getScaleY() == 0) {
+ if (casterProperties.getAlpha() <= 0.0f || casterProperties.getOutline().getAlpha() <= 0.0f ||
+ !casterProperties.getOutline().getPath() || casterProperties.getScaleX() == 0 ||
+ casterProperties.getScaleY() == 0) {
// no shadow to draw
return;
}
- const SkScalar casterAlpha = casterProperties.getAlpha()
- * casterProperties.getOutline().getAlpha();
+ const SkScalar casterAlpha =
+ casterProperties.getAlpha() * casterProperties.getOutline().getAlpha();
if (casterAlpha <= 0.0f) {
return;
}
- float ambientAlpha = (SkiaPipeline::getAmbientShadowAlpha()/255.f)*casterAlpha;
- float spotAlpha = (SkiaPipeline::getSpotShadowAlpha()/255.f)*casterAlpha;
+ float ambientAlpha = (SkiaPipeline::getAmbientShadowAlpha() / 255.f) * casterAlpha;
+ float spotAlpha = (SkiaPipeline::getSpotShadowAlpha() / 255.f) * casterAlpha;
const RevealClip& revealClip = casterProperties.getRevealClip();
const SkPath* revealClipPath = revealClip.getPath();
@@ -163,28 +164,22 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
hwuiMatrix.copyTo(shadowMatrix);
canvas->concat(shadowMatrix);
- const SkPath* casterOutlinePath = casterProperties.getOutline().getPath();
- // holds temporary SkPath to store the result of intersections
- SkPath tmpPath;
- const SkPath* casterPath = casterOutlinePath;
+ // default the shadow-casting path to the outline of the caster
+ const SkPath* casterPath = casterProperties.getOutline().getPath();
+
+ // intersect the shadow-casting path with the clipBounds, if present
+ if (clippedToBounds && !casterClipRect.contains(casterPath->getBounds())) {
+ casterPath = caster->getRenderNode()->getClippedOutline(casterClipRect);
+ }
- // TODO: In to following course of code that calculates the final shape, is there an optimal
- // of doing the Op calculations?
// intersect the shadow-casting path with the reveal, if present
+ SkPath tmpPath; // holds temporary SkPath to store the result of intersections
if (revealClipPath) {
Op(*casterPath, *revealClipPath, kIntersect_SkPathOp, &tmpPath);
tmpPath.setIsVolatile(true);
casterPath = &tmpPath;
}
- // intersect the shadow-casting path with the clipBounds, if present
- if (clippedToBounds) {
- SkPath clipBoundsPath;
- clipBoundsPath.addRect(casterClipRect);
- Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, &tmpPath);
- tmpPath.setIsVolatile(true);
- casterPath = &tmpPath;
- }
const Vector3 lightPos = SkiaPipeline::getLightCenter();
SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
SkPoint3 zParams;
@@ -196,11 +191,14 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
} else {
zParams = SkPoint3::Make(0, 0, casterProperties.getZ());
}
- SkShadowUtils::DrawShadow(canvas, *casterPath, zParams, skiaLightPos,
- SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
- casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
+ SkColor ambientColor = multiplyAlpha(casterProperties.getAmbientShadowColor(), ambientAlpha);
+ SkColor spotColor = multiplyAlpha(casterProperties.getSpotShadowColor(), spotAlpha);
+ SkShadowUtils::DrawShadow(
+ canvas, *casterPath, zParams, skiaLightPos, SkiaPipeline::getLightRadius(),
+ ambientColor, spotColor,
+ casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
}
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
index 9f00d23ae985..3c48d3604864 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
@@ -41,9 +41,7 @@ public:
explicit StartReorderBarrierDrawable(SkiaDisplayList* data);
protected:
- virtual SkRect onGetBounds() override {
- return SkRect::MakeLargest();
- }
+ virtual SkRect onGetBounds() override { return SkRect::MakeLargest(); }
virtual void onDraw(SkCanvas* canvas) override;
private:
@@ -65,16 +63,16 @@ private:
class EndReorderBarrierDrawable : public SkDrawable {
public:
explicit EndReorderBarrierDrawable(StartReorderBarrierDrawable* startBarrier);
+
protected:
- virtual SkRect onGetBounds() override {
- return SkRect::MakeLargest();
- }
+ virtual SkRect onGetBounds() override { return SkRect::MakeLargest(); }
virtual void onDraw(SkCanvas* canvas) override;
+
private:
void drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster);
StartReorderBarrierDrawable* mStartBarrier;
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
new file mode 100644
index 000000000000..670074871c71
--- /dev/null
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ShaderCache.h"
+#include <algorithm>
+#include <log/log.h>
+#include <thread>
+#include "FileBlobCache.h"
+#include "Properties.h"
+#include "utils/TraceUtils.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+// Cache size limits.
+static const size_t maxKeySize = 1024;
+static const size_t maxValueSize = 64 * 1024;
+static const size_t maxTotalSize = 512 * 1024;
+
+ShaderCache::ShaderCache() {
+ // There is an "incomplete FileBlobCache type" compilation error, if ctor is moved to header.
+}
+
+ShaderCache ShaderCache::sCache;
+
+ShaderCache& ShaderCache::get() {
+ return sCache;
+}
+
+void ShaderCache::initShaderDiskCache() {
+ ATRACE_NAME("initShaderDiskCache");
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ // Emulators can switch between different renders either as part of config
+ // or snapshot migration. Also, program binaries may not work well on some
+ // desktop / laptop GPUs. Thus, disable the shader disk cache for emulator builds.
+ if (!Properties::runningInEmulator && mFilename.length() > 0) {
+ mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
+ mInitialized = true;
+ }
+}
+
+void ShaderCache::setFilename(const char* filename) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mFilename = filename;
+}
+
+BlobCache* ShaderCache::getBlobCacheLocked() {
+ LOG_ALWAYS_FATAL_IF(!mInitialized, "ShaderCache has not been initialized");
+ return mBlobCache.get();
+}
+
+sk_sp<SkData> ShaderCache::load(const SkData& key) {
+ ATRACE_NAME("ShaderCache::load");
+ size_t keySize = key.size();
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (!mInitialized) {
+ return nullptr;
+ }
+
+ // mObservedBlobValueSize is reasonably big to avoid memory reallocation
+ // Allocate a buffer with malloc. SkData takes ownership of that allocation and will call free.
+ void* valueBuffer = malloc(mObservedBlobValueSize);
+ if (!valueBuffer) {
+ return nullptr;
+ }
+ BlobCache* bc = getBlobCacheLocked();
+ size_t valueSize = bc->get(key.data(), keySize, valueBuffer, mObservedBlobValueSize);
+ int maxTries = 3;
+ while (valueSize > mObservedBlobValueSize && maxTries > 0) {
+ mObservedBlobValueSize = std::min(valueSize, maxValueSize);
+ void *newValueBuffer = realloc(valueBuffer, mObservedBlobValueSize);
+ if (!newValueBuffer) {
+ free(valueBuffer);
+ return nullptr;
+ }
+ valueBuffer = newValueBuffer;
+ valueSize = bc->get(key.data(), keySize, valueBuffer, mObservedBlobValueSize);
+ maxTries--;
+ }
+ if (!valueSize) {
+ free(valueBuffer);
+ return nullptr;
+ }
+ if (valueSize > mObservedBlobValueSize) {
+ ALOGE("ShaderCache::load value size is too big %d", (int) valueSize);
+ free(valueBuffer);
+ return nullptr;
+ }
+ return SkData::MakeFromMalloc(valueBuffer, valueSize);
+}
+
+void ShaderCache::store(const SkData& key, const SkData& data) {
+ ATRACE_NAME("ShaderCache::store");
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ if (!mInitialized) {
+ return;
+ }
+
+ size_t valueSize = data.size();
+ size_t keySize = key.size();
+ if (keySize == 0 || valueSize == 0 || valueSize >= maxValueSize) {
+ ALOGW("ShaderCache::store: sizes %d %d not allowed", (int)keySize, (int)valueSize);
+ return;
+ }
+
+ const void* value = data.data();
+
+ BlobCache* bc = getBlobCacheLocked();
+ bc->set(key.data(), keySize, value, valueSize);
+
+ if (!mSavePending && mDeferredSaveDelay > 0) {
+ mSavePending = true;
+ std::thread deferredSaveThread([this]() {
+ sleep(mDeferredSaveDelay);
+ std::lock_guard<std::mutex> lock(mMutex);
+ ATRACE_NAME("ShaderCache::saveToDisk");
+ if (mInitialized && mBlobCache) {
+ mBlobCache->writeToFile();
+ }
+ mSavePending = false;
+ });
+ deferredSaveThread.detach();
+ }
+}
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
new file mode 100644
index 000000000000..27473d67bd1a
--- /dev/null
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cutils/compiler.h>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+#include <GrContextOptions.h>
+
+namespace android {
+
+class BlobCache;
+class FileBlobCache;
+
+namespace uirenderer {
+namespace skiapipeline {
+
+class ShaderCache : public GrContextOptions::PersistentCache {
+public:
+ /**
+ * "get" returns a pointer to the singleton ShaderCache object. This
+ * singleton object will never be destroyed.
+ */
+ ANDROID_API static ShaderCache& get();
+
+ /**
+ * "initShaderDiskCache" loads the serialized cache contents from disk and puts the ShaderCache
+ * into an initialized state, such that it is able to insert and retrieve entries from the
+ * cache. This should be called when HWUI pipeline is initialized. When not in the initialized
+ * state the load and store methods will return without performing any cache operations.
+ */
+ virtual void initShaderDiskCache();
+
+ /**
+ * "setFilename" sets the name of the file that should be used to store
+ * cache contents from one program invocation to another. This function does not perform any
+ * disk operation and it should be invoked before "initShaderCache".
+ */
+ virtual void setFilename(const char* filename);
+
+ /**
+ * "load" attempts to retrieve the value blob associated with a given key
+ * blob from cache. This will be called by Skia, when it needs to compile a new SKSL shader.
+ */
+ sk_sp<SkData> load(const SkData& key) override;
+
+ /**
+ * "store" attempts to insert a new key/value blob pair into the cache.
+ * This will be called by Skia after it compiled a new SKSL shader
+ */
+ void store(const SkData& key, const SkData& data) override;
+
+private:
+ // Creation and (the lack of) destruction is handled internally.
+ ShaderCache();
+
+ // Copying is disallowed.
+ ShaderCache(const ShaderCache&) = delete;
+ void operator=(const ShaderCache&) = delete;
+
+ /**
+ * "getBlobCacheLocked" returns the BlobCache object being used to store the
+ * key/value blob pairs. If the BlobCache object has not yet been created,
+ * this will do so, loading the serialized cache contents from disk if
+ * possible.
+ */
+ BlobCache* getBlobCacheLocked();
+
+ /**
+ * "mInitialized" indicates whether the ShaderCache is in the initialized
+ * state. It is initialized to false at construction time, and gets set to
+ * true when initialize is called.
+ * When in this state, the cache behaves as normal. When not,
+ * the load and store methods will return without performing any cache
+ * operations.
+ */
+ bool mInitialized = false;
+
+ /**
+ * "mBlobCache" is the cache in which the key/value blob pairs are stored. It
+ * is initially NULL, and will be initialized by getBlobCacheLocked the
+ * first time it's needed.
+ * The blob cache contains the Android build number. We treat version mismatches as an empty
+ * cache (logic implemented in BlobCache::unflatten).
+ */
+ std::unique_ptr<FileBlobCache> mBlobCache;
+
+ /**
+ * "mFilename" is the name of the file for storing cache contents in between
+ * program invocations. It is initialized to an empty string at
+ * construction time, and can be set with the setCacheFilename method. An
+ * empty string indicates that the cache should not be saved to or restored
+ * from disk.
+ */
+ std::string mFilename;
+
+ /**
+ * "mSavePending" indicates whether or not a deferred save operation is
+ * pending. Each time a key/value pair is inserted into the cache via
+ * load, a deferred save is initiated if one is not already pending.
+ * This will wait some amount of time and then trigger a save of the cache
+ * contents to disk.
+ */
+ bool mSavePending = false;
+
+ /**
+ * "mObservedBlobValueSize" is the maximum value size observed by the cache reading function.
+ */
+ size_t mObservedBlobValueSize = 20*1024;
+
+ /**
+ * The time in seconds to wait before saving newly inserted cache entries.
+ */
+ unsigned int mDeferredSaveDelay = 4;
+
+ /**
+ * "mMutex" is the mutex used to prevent concurrent access to the member
+ * variables. It must be locked whenever the member variables are accessed.
+ */
+ mutable std::mutex mMutex;
+
+ /**
+ * "sCache" is the singleton ShaderCache object.
+ */
+ static ShaderCache sCache;
+
+ friend class ShaderCacheTestUtils; //used for unit testing
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 3ddc09fbeca1..82179a37f5be 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -16,14 +16,13 @@
#include "SkiaDisplayList.h"
-#include "renderthread/CanvasContext.h"
-#include "VectorDrawable.h"
#include "DumpOpsCanvas.h"
#include "SkiaPipeline.h"
+#include "VectorDrawable.h"
+#include "renderthread/CanvasContext.h"
#include <SkImagePriv.h>
-
namespace android {
namespace uirenderer {
namespace skiapipeline {
@@ -32,6 +31,9 @@ void SkiaDisplayList::syncContents() {
for (auto& functor : mChildFunctors) {
functor.syncFunctor();
}
+ for (auto& animatedImage : mAnimatedImages) {
+ animatedImage->syncProperties();
+ }
for (auto& vectorDrawable : mVectorDrawables) {
vectorDrawable->syncProperties();
}
@@ -49,8 +51,8 @@ void SkiaDisplayList::updateChildren(std::function<void(RenderNode*)> updateFn)
}
}
-bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& info,
- bool functorsNeedLayer,
+bool SkiaDisplayList::prepareListAndChildren(
+ TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
// If the prepare tree is triggered by the UI thread and no previous call to
// pinImages has failed then we must pin all mutable images in the GPU cache
@@ -64,7 +66,7 @@ bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& i
}
bool hasBackwardProjectedNodesHere = false;
- bool hasBackwardProjectedNodesSubtree= false;
+ bool hasBackwardProjectedNodesSubtree = false;
for (auto& child : mChildNodes) {
hasBackwardProjectedNodesHere |= child.getNodeProperties().getProjectBackwards();
@@ -78,23 +80,41 @@ bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& i
info.damageAccumulator->popTransform();
}
- //The purpose of next block of code is to reset projected display list if there are no
- //backward projected nodes. This speeds up drawing, by avoiding an extra walk of the tree
+ // The purpose of next block of code is to reset projected display list if there are no
+ // backward projected nodes. This speeds up drawing, by avoiding an extra walk of the tree
if (mProjectionReceiver) {
- mProjectionReceiver->setProjectedDisplayList(hasBackwardProjectedNodesSubtree ? this : nullptr);
+ mProjectionReceiver->setProjectedDisplayList(hasBackwardProjectedNodesSubtree ? this
+ : nullptr);
info.hasBackwardProjectedNodes = hasBackwardProjectedNodesHere;
} else {
- info.hasBackwardProjectedNodes = hasBackwardProjectedNodesSubtree
- || hasBackwardProjectedNodesHere;
+ info.hasBackwardProjectedNodes =
+ hasBackwardProjectedNodesSubtree || hasBackwardProjectedNodesHere;
}
bool isDirty = false;
+ for (auto& animatedImage : mAnimatedImages) {
+ nsecs_t timeTilNextFrame = TreeInfo::Out::kNoAnimatedImageDelay;
+ // If any animated image in the display list needs updated, then damage the node.
+ if (animatedImage->isDirty(&timeTilNextFrame)) {
+ isDirty = true;
+ }
+
+ if (animatedImage->isRunning() &&
+ timeTilNextFrame != TreeInfo::Out::kNoAnimatedImageDelay) {
+ auto& delay = info.out.animatedImageDelay;
+ if (delay == TreeInfo::Out::kNoAnimatedImageDelay || timeTilNextFrame < delay) {
+ delay = timeTilNextFrame;
+ }
+ }
+ }
+
for (auto& vectorDrawable : mVectorDrawables) {
// If any vector drawable in the display list needs update, damage the node.
if (vectorDrawable->isDirty()) {
isDirty = true;
static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
- ->getVectorDrawables()->push_back(vectorDrawable);
+ ->getVectorDrawables()
+ ->push_back(vectorDrawable);
}
vectorDrawable->setPropertyChangeWillBeConsumed(true);
}
@@ -108,6 +128,7 @@ void SkiaDisplayList::reset() {
mMutableImages.clear();
mVectorDrawables.clear();
+ mAnimatedImages.clear();
mChildFunctors.clear();
mChildNodes.clear();
@@ -121,6 +142,6 @@ void SkiaDisplayList::output(std::ostream& output, uint32_t level) {
mDisplayList.draw(&canvas);
}
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 66375d13826c..818ec114a5b3 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -17,12 +17,13 @@
#pragma once
#include "DisplayList.h"
+#include "hwui/AnimatedImageDrawable.h"
#include "GLFunctorDrawable.h"
#include "RenderNodeDrawable.h"
-#include <deque>
#include <SkLiteDL.h>
#include <SkLiteRecorder.h>
+#include <deque>
namespace android {
namespace uirenderer {
@@ -62,7 +63,7 @@ public:
* need to monitor that they don't extend beyond the lifetime of the class
* that creates them. Allocator dtor invokes all SkDrawable dtors.
*/
- template<class T, typename... Params>
+ template <class T, typename... Params>
SkDrawable* allocateDrawable(Params&&... params) {
return allocator.create<T>(std::forward<Params>(params)...);
}
@@ -113,7 +114,8 @@ public:
* to subclass from DisplayList
*/
- bool prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+ bool prepareListAndChildren(
+ TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) override;
/**
@@ -143,26 +145,28 @@ public:
std::deque<GLFunctorDrawable> mChildFunctors;
std::vector<SkImage*> mMutableImages;
std::vector<VectorDrawableRoot*> mVectorDrawables;
+ std::vector<AnimatedImageDrawable*> mAnimatedImages;
SkLiteDL mDisplayList;
- //mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
- //receiver. It is set at record time and used at both prepare and draw tree traversals to
- //make sure backward projected nodes are found and drawn immediately after mProjectionReceiver.
+ // mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
+ // receiver. It is set at record time and used at both prepare and draw tree traversals to
+ // make sure backward projected nodes are found and drawn immediately after mProjectionReceiver.
RenderNodeDrawable* mProjectionReceiver = nullptr;
- //mProjectedOutline is valid only when render node tree is traversed during the draw pass.
- //Render nodes that have a child receiver node, will store a pointer to their outline in
- //mProjectedOutline. Child receiver node will apply the clip before any backward projected
- //node is drawn.
+ // mProjectedOutline is valid only when render node tree is traversed during the draw pass.
+ // Render nodes that have a child receiver node, will store a pointer to their outline in
+ // mProjectedOutline. Child receiver node will apply the clip before any backward projected
+ // node is drawn.
const Outline* mProjectedOutline = nullptr;
- //mProjectedReceiverParentMatrix is valid when render node tree is traversed during the draw
- //pass. Render nodes that have a child receiver node, will store their matrix in
- //mProjectedReceiverParentMatrix. Child receiver node will set the matrix and then clip with the
- //outline of their parent.
+ // mProjectedReceiverParentMatrix is valid when render node tree is traversed during the draw
+ // pass. Render nodes that have a child receiver node, will store their matrix in
+ // mProjectedReceiverParentMatrix. Child receiver node will set the matrix and then clip with
+ // the
+ // outline of their parent.
SkMatrix mProjectedReceiverParentMatrix;
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaLayer.h b/libs/hwui/pipeline/skia/SkiaLayer.h
index 904d57e073ca..82e6914e8b7f 100644
--- a/libs/hwui/pipeline/skia/SkiaLayer.h
+++ b/libs/hwui/pipeline/skia/SkiaLayer.h
@@ -26,14 +26,12 @@ namespace skiapipeline {
/**
* An offscreen rendering target used to contain the contents a RenderNode.
*/
-struct SkiaLayer
-{
+struct SkiaLayer {
sk_sp<SkSurface> layerSurface;
Matrix4 inverseTransformInWindow;
bool hasRenderedSinceRepaint = false;
};
-
} /* namespace skiapipeline */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp b/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
new file mode 100644
index 000000000000..ee996224fee6
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SkiaMemoryTracer.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+SkiaMemoryTracer::SkiaMemoryTracer(std::vector<ResourcePair> resourceMap, bool itemizeType)
+ : mResourceMap(resourceMap)
+ , mItemizeType(itemizeType)
+ , mTotalSize("bytes", 0)
+ , mPurgeableSize("bytes", 0) {}
+
+SkiaMemoryTracer::SkiaMemoryTracer(const char* categoryKey, bool itemizeType)
+ : mCategoryKey(categoryKey)
+ , mItemizeType(itemizeType)
+ , mTotalSize("bytes", 0)
+ , mPurgeableSize("bytes", 0) {}
+
+const char* SkiaMemoryTracer::mapName(const char* resourceName) {
+ for (auto& resource : mResourceMap) {
+ if (SkStrContains(resourceName, resource.first)) {
+ return resource.second;
+ }
+ }
+ return nullptr;
+}
+
+void SkiaMemoryTracer::processElement() {
+ if(!mCurrentElement.empty()) {
+ // Only count elements that contain "size", other values just provide metadata.
+ auto sizeResult = mCurrentValues.find("size");
+ if (sizeResult != mCurrentValues.end()) {
+ mTotalSize.value += sizeResult->second.value;
+ mTotalSize.count++;
+ } else {
+ mCurrentElement.clear();
+ mCurrentValues.clear();
+ return;
+ }
+
+ // find the purgeable size if one exists
+ auto purgeableResult = mCurrentValues.find("purgeable_size");
+ if (purgeableResult != mCurrentValues.end()) {
+ mPurgeableSize.value += purgeableResult->second.value;
+ mPurgeableSize.count++;
+ }
+
+ // find the type if one exists
+ const char* type;
+ auto typeResult = mCurrentValues.find("type");
+ if (typeResult != mCurrentValues.end()) {
+ type = typeResult->second.units;
+ } else if (mItemizeType) {
+ type = "Other";
+ }
+
+ // compute the type if we are itemizing or use the default "size" if we are not
+ const char* key = (mItemizeType) ? type : sizeResult->first;
+ SkASSERT(key != nullptr);
+
+ // compute the top level element name using either the map or category key
+ const char* resourceName = mapName(mCurrentElement.c_str());
+ if (mCategoryKey != nullptr) {
+ // find the category if one exists
+ auto categoryResult = mCurrentValues.find(mCategoryKey);
+ if (categoryResult != mCurrentValues.end()) {
+ resourceName = categoryResult->second.units;
+ } else if (mItemizeType) {
+ resourceName = "Other";
+ }
+ }
+
+ // if we don't have a resource name then we don't know how to label the
+ // data and should abort.
+ if (resourceName == nullptr) {
+ mCurrentElement.clear();
+ mCurrentValues.clear();
+ return;
+ }
+
+ auto result = mResults.find(resourceName);
+ if (result != mResults.end()) {
+ auto& resourceValues = result->second;
+ typeResult = resourceValues.find(key);
+ if (typeResult != resourceValues.end()) {
+ SkASSERT(sizeResult->second.units == typeResult->second.units);
+ typeResult->second.value += sizeResult->second.value;
+ typeResult->second.count++;
+ } else {
+ resourceValues.insert({key, sizeResult->second});
+ }
+ } else {
+ mCurrentValues.clear();
+ mCurrentValues.insert({key, sizeResult->second});
+ mResults.insert({resourceName, mCurrentValues});
+ }
+ }
+
+ mCurrentElement.clear();
+ mCurrentValues.clear();
+}
+
+void SkiaMemoryTracer::dumpNumericValue(const char* dumpName, const char* valueName,
+ const char* units, uint64_t value) {
+ if (mCurrentElement != dumpName) {
+ processElement();
+ mCurrentElement = dumpName;
+ }
+ mCurrentValues.insert({valueName, {units, value}});
+}
+
+void SkiaMemoryTracer::logOutput(String8& log) {
+ // process any remaining elements
+ processElement();
+
+ for (const auto& namedItem : mResults) {
+ if (mItemizeType) {
+ log.appendFormat(" %s:\n", namedItem.first.c_str());
+ for (const auto& typedValue : namedItem.second) {
+ TraceValue traceValue = convertUnits(typedValue.second);
+ const char* entry = (traceValue.count > 1) ? "entries" : "entry";
+ log.appendFormat(" %s: %.2f %s (%d %s)\n", typedValue.first,
+ traceValue.value, traceValue.units, traceValue.count, entry);
+ }
+ } else {
+ auto result = namedItem.second.find("size");
+ if (result != namedItem.second.end()) {
+ TraceValue traceValue = convertUnits(result->second);
+ const char* entry = (traceValue.count > 1) ? "entries" : "entry";
+ log.appendFormat(" %s: %.2f %s (%d %s)\n", namedItem.first.c_str(),
+ traceValue.value, traceValue.units, traceValue.count, entry);
+ }
+ }
+ }
+}
+
+void SkiaMemoryTracer::logTotals(String8& log) {
+ TraceValue total = convertUnits(mTotalSize);
+ TraceValue purgeable = convertUnits(mPurgeableSize);
+ log.appendFormat(" %.0f bytes, %.2f %s (%.2f %s is purgeable)\n", mTotalSize.value,
+ total.value, total.units, purgeable.value, purgeable.units);
+}
+
+SkiaMemoryTracer::TraceValue SkiaMemoryTracer::convertUnits(const TraceValue& value) {
+ TraceValue output(value);
+ if (SkString("bytes") == SkString(output.units) && output.value >= 1024) {
+ output.value = output.value / 1024.0f;
+ output.units = "KB";
+ }
+ if (SkString("KB") == SkString(output.units) && output.value >= 1024) {
+ output.value = output.value / 1024.0f;
+ output.units = "MB";
+ }
+ return output;
+}
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaMemoryTracer.h b/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
new file mode 100644
index 000000000000..abf1f4b052ce
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <SkString.h>
+#include <SkTraceMemoryDump.h>
+#include <utils/String8.h>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+typedef std::pair<const char*, const char*> ResourcePair;
+
+class SkiaMemoryTracer : public SkTraceMemoryDump {
+public:
+ SkiaMemoryTracer(std::vector<ResourcePair> resourceMap, bool itemizeType);
+ SkiaMemoryTracer(const char* categoryKey, bool itemizeType);
+ ~SkiaMemoryTracer() override {}
+
+ void logOutput(String8& log);
+ void logTotals(String8& log);
+
+ void dumpNumericValue(const char* dumpName, const char* valueName, const char* units,
+ uint64_t value) override;
+
+ void dumpStringValue(const char* dumpName, const char* valueName, const char* value) override {
+ // for convenience we just store this in the same format as numerical values
+ dumpNumericValue(dumpName, valueName, value, 0);
+ }
+
+ LevelOfDetail getRequestedDetails() const override {
+ return SkTraceMemoryDump::kLight_LevelOfDetail;
+ }
+
+ bool shouldDumpWrappedObjects() const override { return true; }
+ void setMemoryBacking(const char*, const char*, const char*) override { }
+ void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override { }
+
+private:
+ struct TraceValue {
+ TraceValue(const char* units, uint64_t value) : units(units), value(value), count(1) {}
+ TraceValue(const TraceValue& v) : units(v.units), value(v.value), count(v.count) {}
+
+ const char* units;
+ float value;
+ int count;
+ };
+
+ const char* mapName(const char* resourceName);
+ void processElement();
+ TraceValue convertUnits(const TraceValue& value);
+
+ const std::vector<ResourcePair> mResourceMap;
+ const char* mCategoryKey = nullptr;
+ const bool mItemizeType;
+
+ // variables storing the size of all elements being dumped
+ TraceValue mTotalSize;
+ TraceValue mPurgeableSize;
+
+ // variables storing information on the current node being dumped
+ std::string mCurrentElement;
+ std::unordered_map<const char*, TraceValue> mCurrentValues;
+
+ // variable that stores the final format of the data after the individual elements are processed
+ std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mResults;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */ \ No newline at end of file
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 925db303461f..270527d551a9 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -16,18 +16,20 @@
#include "SkiaOpenGLPipeline.h"
-#include "hwui/Bitmap.h"
#include "DeferredLayerUpdater.h"
#include "GlLayer.h"
#include "LayerDrawable.h"
-#include "renderthread/EglManager.h"
-#include "renderthread/Frame.h"
-#include "renderstate/RenderState.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
+#include "hwui/Bitmap.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/Frame.h"
#include "utils/TraceUtils.h"
#include <GrBackendSurface.h>
+#include <SkImageInfo.h>
+#include <SkBlendMode.h>
#include <cutils/properties.h>
#include <strings.h>
@@ -39,9 +41,7 @@ namespace uirenderer {
namespace skiapipeline {
SkiaOpenGLPipeline::SkiaOpenGLPipeline(RenderThread& thread)
- : SkiaPipeline(thread)
- , mEglManager(thread.eglManager()) {
-}
+ : SkiaPipeline(thread), mEglManager(thread.eglManager()) {}
MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
// TODO: Figure out why this workaround is needed, see b/13913604
@@ -55,27 +55,27 @@ MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
Frame SkiaOpenGLPipeline::getFrame() {
LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
- "drawRenderNode called on a context with no surface!");
+ "drawRenderNode called on a context with no surface!");
return mEglManager.beginFrame(mEglSurface);
}
-bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty,
- const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector<sp<RenderNode>>& renderNodes,
- FrameInfoVisualizer* profiler) {
-
+bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
+ bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) {
mEglManager.damageFrame(frame, dirty);
// setup surface for fbo0
GrGLFramebufferInfo fboInfo;
fboInfo.fFBOID = 0;
+ GrPixelConfig pixelConfig =
+ wideColorGamut ? kRGBA_half_GrPixelConfig : kRGBA_8888_GrPixelConfig;
GrBackendRenderTarget backendRT(frame.width(), frame.height(), 0, STENCIL_BUFFER_SIZE,
- kRGBA_8888_GrPixelConfig, fboInfo);
+ pixelConfig, fboInfo);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
@@ -84,13 +84,13 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty,
mRenderThread.getGrContext(), backendRT, kBottomLeft_GrSurfaceOrigin, nullptr, &props));
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
- renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, wideColorGamut,
- contentDrawBounds, surface);
+ renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, wideColorGamut, contentDrawBounds,
+ surface);
layerUpdateQueue->clear();
// Draw visual debugging features
- if (CC_UNLIKELY(Properties::showDirtyRegions
- || ProfileType::None != Properties::getProfileType())) {
+ if (CC_UNLIKELY(Properties::showDirtyRegions ||
+ ProfileType::None != Properties::getProfileType())) {
SkCanvas* profileCanvas = surface->getCanvas();
SkiaProfileRenderer profileRenderer(profileCanvas);
profiler->draw(profileRenderer);
@@ -105,9 +105,8 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty,
return true;
}
-bool SkiaOpenGLPipeline::swapBuffers(const Frame& frame, bool drew,
- const SkRect& screenDirty, FrameInfo* currentFrameInfo, bool* requireSwap) {
-
+bool SkiaOpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
+ FrameInfo* currentFrameInfo, bool* requireSwap) {
GL_CHECKPOINT(LOW);
// Even if we decided to cancel the frame, from the perspective of jank
@@ -132,15 +131,61 @@ bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBi
deferredLayer->updateTexImage();
deferredLayer->apply();
- SkCanvas canvas(*bitmap);
+ // drop the colorSpace as we only support readback into sRGB or extended sRGB
+ SkImageInfo surfaceInfo = bitmap->info().makeColorSpace(nullptr);
+
+ /* This intermediate surface is present to work around a bug in SwiftShader that
+ * prevents us from reading the contents of the layer's texture directly. The
+ * workaround involves first rendering that texture into an intermediate buffer and
+ * then reading from the intermediate buffer into the bitmap.
+ */
+ sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
+ SkBudgeted::kYes, surfaceInfo);
+
+ if (!tmpSurface.get()) {
+ surfaceInfo = surfaceInfo.makeColorType(SkColorType::kN32_SkColorType);
+ tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
+ SkBudgeted::kYes, surfaceInfo);
+ if (!tmpSurface.get()) {
+ ALOGW("Unable to readback GPU contents into the provided bitmap");
+ return false;
+ }
+ }
+
Layer* layer = deferredLayer->backingLayer();
- return LayerDrawable::DrawLayer(mRenderThread.getGrContext(), &canvas, layer);
+ const SkRect dstRect = SkRect::MakeIWH(bitmap->width(), bitmap->height());
+ if (LayerDrawable::DrawLayer(mRenderThread.getGrContext(), tmpSurface->getCanvas(), layer,
+ &dstRect)) {
+ sk_sp<SkImage> tmpImage = tmpSurface->makeImageSnapshot();
+ if (tmpImage->readPixels(surfaceInfo, bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
+ bitmap->notifyPixelsChanged();
+ return true;
+ }
+
+ // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into 8888
+ // and then draw that into the destination format before giving up.
+ SkBitmap tmpBitmap;
+ SkImageInfo bitmapInfo = SkImageInfo::MakeN32(bitmap->width(), bitmap->height(),
+ bitmap->alphaType());
+ if (tmpBitmap.tryAllocPixels(bitmapInfo) &&
+ tmpImage->readPixels(bitmapInfo, tmpBitmap.getPixels(),
+ tmpBitmap.rowBytes(), 0, 0)) {
+ SkCanvas canvas(*bitmap);
+ SkPaint paint;
+ paint.setBlendMode(SkBlendMode::kSrc);
+ canvas.drawBitmap(tmpBitmap, 0, 0, &paint);
+ bitmap->notifyPixelsChanged();
+ return true;
+ }
+ }
+
+ return false;
}
static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
- SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
- GlLayer* layer = new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha,
- mode, blend);
+ sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend) {
+ GlLayer* layer =
+ new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
layer->generateTexture();
return layer;
}
@@ -157,8 +202,7 @@ void SkiaOpenGLPipeline::onStop() {
}
bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
- ColorMode colorMode) {
-
+ ColorMode colorMode) {
if (mEglSurface != EGL_NO_SURFACE) {
mEglManager.destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
@@ -204,8 +248,7 @@ void SkiaOpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* func
class AutoEglFence {
public:
- AutoEglFence(EGLDisplay display)
- : mDisplay(display) {
+ AutoEglFence(EGLDisplay display) : mDisplay(display) {
fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
}
@@ -216,17 +259,17 @@ public:
}
EGLSyncKHR fence = EGL_NO_SYNC_KHR;
+
private:
EGLDisplay mDisplay = EGL_NO_DISPLAY;
};
class AutoEglImage {
public:
- AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
- : mDisplay(display) {
- EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
- image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
+ AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer) : mDisplay(display) {
+ EGLint imageAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+ image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer,
+ imageAttrs);
}
~AutoEglImage() {
@@ -236,6 +279,7 @@ public:
}
EGLImageKHR image = EGL_NO_IMAGE_KHR;
+
private:
EGLDisplay mDisplay = EGL_NO_DISPLAY;
};
@@ -247,16 +291,34 @@ public:
glBindTexture(GL_TEXTURE_2D, mTexture);
}
- ~AutoSkiaGlTexture() {
- glDeleteTextures(1, &mTexture);
- }
+ ~AutoSkiaGlTexture() { glDeleteTextures(1, &mTexture); }
private:
GLuint mTexture = 0;
};
+static bool isFP16Supported(const sk_sp<GrContext>& grContext) {
+ static std::once_flag sOnceFlag;
+ static bool supported = false;
+
+ std::call_once(sOnceFlag, [](const sk_sp<GrContext>& grContext) {
+ if (!grContext->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
+ supported = false;
+ return;
+ }
+
+ sp<GraphicBuffer> buffer = new GraphicBuffer(1, 1, PIXEL_FORMAT_RGBA_FP16,
+ GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
+ GraphicBuffer::USAGE_SW_READ_NEVER, "tempFp16Buffer");
+ status_t error = buffer->initCheck();
+ supported = !error;
+ }, grContext);
+
+ return supported;
+}
+
sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
- SkBitmap& skBitmap) {
+ SkBitmap& skBitmap) {
renderThread.eglManager().initialize();
sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
@@ -265,73 +327,67 @@ sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThr
GLint format, type;
bool isSupported = false;
- //TODO: add support for linear blending (when ANDROID_ENABLE_LINEAR_BLENDING is defined)
+ // TODO: add support for linear blending (when ANDROID_ENABLE_LINEAR_BLENDING is defined)
switch (info.colorType()) {
- case kRGBA_8888_SkColorType:
- isSupported = true;
- // ARGB_4444 is upconverted to RGBA_8888
- case kARGB_4444_SkColorType:
- pixelFormat = PIXEL_FORMAT_RGBA_8888;
- format = GL_RGBA;
- type = GL_UNSIGNED_BYTE;
- break;
- case kRGBA_F16_SkColorType:
- isSupported = grContext->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig);
- if (isSupported) {
- type = GL_HALF_FLOAT;
- pixelFormat = PIXEL_FORMAT_RGBA_FP16;
- } else {
+ case kRGBA_8888_SkColorType:
+ isSupported = true;
+ // ARGB_4444 is upconverted to RGBA_8888
+ case kARGB_4444_SkColorType:
+ pixelFormat = PIXEL_FORMAT_RGBA_8888;
+ format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
+ break;
+ case kRGBA_F16_SkColorType:
+ isSupported = isFP16Supported(grContext);
+ if (isSupported) {
+ type = GL_HALF_FLOAT;
+ pixelFormat = PIXEL_FORMAT_RGBA_FP16;
+ } else {
+ type = GL_UNSIGNED_BYTE;
+ pixelFormat = PIXEL_FORMAT_RGBA_8888;
+ }
+ format = GL_RGBA;
+ break;
+ case kRGB_565_SkColorType:
+ isSupported = true;
+ pixelFormat = PIXEL_FORMAT_RGB_565;
+ format = GL_RGB;
+ type = GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case kGray_8_SkColorType:
+ isSupported = true;
pixelFormat = PIXEL_FORMAT_RGBA_8888;
- }
- format = GL_RGBA;
- break;
- case kRGB_565_SkColorType:
- isSupported = true;
- pixelFormat = PIXEL_FORMAT_RGB_565;
- format = GL_RGB;
- type = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case kGray_8_SkColorType:
- isSupported = true;
- pixelFormat = PIXEL_FORMAT_RGBA_8888;
- format = GL_LUMINANCE;
- type = GL_UNSIGNED_BYTE;
- break;
- default:
- ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
- return nullptr;
- }
-
- auto colorSpace = info.colorSpace();
- bool convertToSRGB = false;
- if (colorSpace && (!colorSpace->isSRGB())) {
- isSupported = false;
- convertToSRGB = true;
+ format = GL_LUMINANCE;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
+ return nullptr;
}
SkBitmap bitmap;
if (isSupported) {
bitmap = skBitmap;
} else {
- bitmap.allocPixels(SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType(),
- nullptr));
+ bitmap.allocPixels(
+ SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType(), nullptr));
bitmap.eraseColor(0);
- if (info.colorType() == kRGBA_F16_SkColorType || convertToSRGB) {
+ if (info.colorType() == kRGBA_F16_SkColorType) {
// Drawing RGBA_F16 onto ARGB_8888 is not supported
skBitmap.readPixels(bitmap.info().makeColorSpace(SkColorSpace::MakeSRGB()),
- bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
+ bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
} else {
SkCanvas canvas(bitmap);
canvas.drawBitmap(skBitmap, 0.0f, 0.0f, nullptr);
}
}
- sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
- GraphicBuffer::USAGE_HW_TEXTURE |
- GraphicBuffer::USAGE_SW_WRITE_NEVER |
- GraphicBuffer::USAGE_SW_READ_NEVER,
- std::string("Bitmap::allocateSkiaHardwareBitmap pid [") + std::to_string(getpid()) + "]");
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ info.width(), info.height(), pixelFormat,
+ GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
+ GraphicBuffer::USAGE_SW_READ_NEVER,
+ std::string("Bitmap::allocateSkiaHardwareBitmap pid [") + std::to_string(getpid()) +
+ "]");
status_t error = buffer->initCheck();
if (error < 0) {
@@ -339,18 +395,17 @@ sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThr
return nullptr;
}
- //upload the bitmap into a texture
+ // upload the bitmap into a texture
EGLDisplay display = eglGetCurrentDisplay();
- LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
- "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
- uirenderer::renderthread::EglManager::eglErrorString());
+ LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+ uirenderer::renderthread::EglManager::eglErrorString());
// We use an EGLImage to access the content of the GraphicBuffer
// The EGL image is later bound to a 2D texture
- EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
+ EGLClientBuffer clientBuffer = (EGLClientBuffer)buffer->getNativeBuffer();
AutoEglImage autoImage(display, clientBuffer);
if (autoImage.image == EGL_NO_IMAGE_KHR) {
ALOGW("Could not create EGL image, err =%s",
- uirenderer::renderthread::EglManager::eglErrorString());
+ uirenderer::renderthread::EglManager::eglErrorString());
return nullptr;
}
AutoSkiaGlTexture glTexture;
@@ -361,7 +416,7 @@ sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThr
// But asynchronous in sense that driver may upload texture onto hardware buffer when we first
// use it in drawing
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info.width(), info.height(), format, type,
- bitmap.getPixels());
+ bitmap.getPixels());
GL_CHECKPOINT(MODERATE);
// The fence is used to wait for the texture upload to finish
@@ -375,7 +430,7 @@ sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThr
// The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
// pipeline flush (similar to what a glFlush() would do.)
EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
return nullptr;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index aa29c8e3babc..5e013b6697a7 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -33,25 +33,24 @@ public:
renderthread::MakeCurrentResult makeCurrent() override;
renderthread::Frame getFrame() override;
bool draw(const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) override;
+ const FrameBuilder::LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+ const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode> >& renderNodes,
+ FrameInfoVisualizer* profiler) override;
bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) override;
+ FrameInfo* currentFrameInfo, bool* requireSwap) override;
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
- renderthread::ColorMode colorMode) override;
+ renderthread::ColorMode colorMode) override;
void onStop() override;
bool isSurfaceReady() override;
bool isContextReady() override;
static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
- SkBitmap& skBitmap);
+ SkBitmap& skBitmap);
private:
renderthread::EglManager& mEglManager;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 311419dd2b65..107890e57a19 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -16,15 +16,16 @@
#include "SkiaOpenGLReadback.h"
-#include "Matrix.h"
-#include "Properties.h"
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GrBackendSurface.h>
#include <SkCanvas.h>
#include <SkSurface.h>
-#include <GrBackendSurface.h>
#include <gl/GrGLInterface.h>
#include <gl/GrGLTypes.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
+#include "DeviceInfo.h"
+#include "Matrix.h"
+#include "Properties.h"
using namespace android::uirenderer::renderthread;
@@ -33,8 +34,8 @@ namespace uirenderer {
namespace skiapipeline {
CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
- int imgWidth, int imgHeight, const Rect& srcRect, SkBitmap* bitmap) {
-
+ int imgWidth, int imgHeight, const Rect& srcRect,
+ SkBitmap* bitmap) {
GLuint sourceTexId;
glGenTextures(1, &sourceTexId);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
@@ -44,8 +45,7 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
LOG_ALWAYS_FATAL_IF(!glInterface.get());
- grContext.reset(GrContext::Create(GrBackend::kOpenGL_GrBackend,
- (GrBackendContext)glInterface.get()));
+ grContext = GrContext::MakeGL(std::move(glInterface));
} else {
grContext->resetContext();
}
@@ -54,56 +54,76 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4
externalTexture.fTarget = GL_TEXTURE_EXTERNAL_OES;
externalTexture.fID = sourceTexId;
- GrBackendTexture backendTexture(imgWidth, imgHeight, kRGBA_8888_GrPixelConfig, externalTexture);
+ GrPixelConfig pixelConfig;
+ switch (bitmap->colorType()) {
+ case kRGBA_F16_SkColorType:
+ pixelConfig = kRGBA_half_GrPixelConfig;
+ break;
+ case kN32_SkColorType:
+ default:
+ pixelConfig = kRGBA_8888_GrPixelConfig;
+ break;
+ }
+
+ if (pixelConfig == kRGBA_half_GrPixelConfig &&
+ !grContext->caps()->isConfigRenderable(kRGBA_half_GrPixelConfig, false)) {
+ ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
+ return CopyResult::DestinationInvalid;
+ }
+
+ GrBackendTexture backendTexture(imgWidth, imgHeight, pixelConfig, externalTexture);
CopyResult copyResult = CopyResult::UnknownError;
sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), backendTexture,
- kTopLeft_GrSurfaceOrigin));
+ kTopLeft_GrSurfaceOrigin));
if (image) {
- SkMatrix textureMatrix;
- imgTransform.copyTo(textureMatrix);
-
- // remove the y-flip applied to the matrix
- SkMatrix yFlip = SkMatrix::MakeScale(1, -1);
- yFlip.postTranslate(0,1);
- textureMatrix.preConcat(yFlip);
-
- // multiply by image size, because textureMatrix maps to [0..1] range
- textureMatrix[SkMatrix::kMTransX] *= imgWidth;
- textureMatrix[SkMatrix::kMTransY] *= imgHeight;
-
- // swap rotation and translation part of the matrix, because we convert from
- // right-handed Cartesian to left-handed coordinate system.
- std::swap(textureMatrix[SkMatrix::kMTransX], textureMatrix[SkMatrix::kMTransY]);
- std::swap(textureMatrix[SkMatrix::kMSkewX], textureMatrix[SkMatrix::kMSkewY]);
-
- // convert to Skia data structures
- SkRect skiaSrcRect = srcRect.toSkRect();
- SkMatrix textureMatrixInv;
+ int displayedWidth = imgWidth, displayedHeight = imgHeight;
+ // If this is a 90 or 270 degree rotation we need to swap width/height to get the device
+ // size.
+ if (imgTransform[Matrix4::kSkewX] >= 0.5f || imgTransform[Matrix4::kSkewX] <= -0.5f) {
+ std::swap(displayedWidth, displayedHeight);
+ }
SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
- bool srcNotEmpty = false;
- if (textureMatrix.invert(&textureMatrixInv)) {
- if (skiaSrcRect.isEmpty()) {
- skiaSrcRect = SkRect::MakeIWH(imgWidth, imgHeight);
- srcNotEmpty = !skiaSrcRect.isEmpty();
- } else {
- // src and dest rectangles need to be converted into texture coordinates before the
- // rotation matrix is applied (because drawImageRect preconcat its matrix).
- textureMatrixInv.mapRect(&skiaSrcRect);
- srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(imgWidth, imgHeight));
- }
- textureMatrixInv.mapRect(&skiaDestRect);
+ SkRect skiaSrcRect = srcRect.toSkRect();
+ if (skiaSrcRect.isEmpty()) {
+ skiaSrcRect = SkRect::MakeIWH(displayedWidth, displayedHeight);
}
+ bool srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(displayedWidth, displayedHeight));
if (srcNotEmpty) {
+ SkMatrix textureMatrixInv;
+ imgTransform.copyTo(textureMatrixInv);
+ // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
+ // use bottom left origin and remove flipV and invert transformations.
+ SkMatrix flipV;
+ flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
+ textureMatrixInv.preConcat(flipV);
+ textureMatrixInv.preScale(1.0f / displayedWidth, 1.0f / displayedHeight);
+ textureMatrixInv.postScale(imgWidth, imgHeight);
+ SkMatrix textureMatrix;
+ if (!textureMatrixInv.invert(&textureMatrix)) {
+ textureMatrix = textureMatrixInv;
+ }
+
+ textureMatrixInv.mapRect(&skiaSrcRect);
+ textureMatrixInv.mapRect(&skiaDestRect);
+
// we render in an offscreen buffer to scale and to avoid an issue b/62262733
// with reading incorrect data from EGLImage backed SkImage (likely a driver bug)
- sk_sp<SkSurface> scaledSurface = SkSurface::MakeRenderTarget(
- grContext.get(), SkBudgeted::kYes, bitmap->info());
+ sk_sp<SkSurface> scaledSurface =
+ SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kYes, bitmap->info());
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc);
+ // Apply a filter, which is matching OpenGL pipeline readback behaviour. Filter usage
+ // is codified by tests using golden images like DecodeAccuracyTest.
+ if (skiaSrcRect.width() != bitmap->width() ||
+ skiaSrcRect.height() != bitmap->height()) {
+ // TODO: apply filter always, but check if tests will be fine
+ paint.setFilterQuality(kLow_SkFilterQuality);
+ }
scaledSurface->getCanvas()->concat(textureMatrix);
- scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint);
+ scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint,
+ SkCanvas::kFast_SrcRectConstraint);
image = scaledSurface->makeImageSnapshot();
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h
index d914409628d0..cc9fb3b0a5e0 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h
@@ -25,9 +25,11 @@ namespace skiapipeline {
class SkiaOpenGLReadback : public OpenGLReadback {
public:
SkiaOpenGLReadback(renderthread::RenderThread& thread) : OpenGLReadback(thread) {}
+
protected:
virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
- int imgWidth, int imgHeight, const Rect& srcRect, SkBitmap* bitmap) override;
+ int imgWidth, int imgHeight, const Rect& srcRect,
+ SkBitmap* bitmap) override;
};
} /* namespace skiapipeline */
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 03792e0ed291..d66cba12ad99 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -16,16 +16,15 @@
#include "SkiaPipeline.h"
-#include "utils/TraceUtils.h"
#include <SkImageEncoder.h>
#include <SkImagePriv.h>
#include <SkOverdrawCanvas.h>
#include <SkOverdrawColorFilter.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>
-#include <SkPixelSerializer.h>
-#include <SkStream.h>
+#include "TreeInfo.h"
#include "VectorDrawable.h"
+#include "utils/TraceUtils.h"
#include <unistd.h>
@@ -35,21 +34,26 @@ namespace android {
namespace uirenderer {
namespace skiapipeline {
-float SkiaPipeline::mLightRadius = 0;
+float SkiaPipeline::mLightRadius = 0;
uint8_t SkiaPipeline::mAmbientShadowAlpha = 0;
uint8_t SkiaPipeline::mSpotShadowAlpha = 0;
Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
-SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) {
+SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) {
mVectorDrawables.reserve(30);
}
+SkiaPipeline::~SkiaPipeline() {
+ unpinImages();
+}
+
TaskManager* SkiaPipeline::getTaskManager() {
- return &mTaskManager;
+ return mRenderThread.cacheManager().getTaskManager();
}
void SkiaPipeline::onDestroyHardwareResources() {
+ unpinImages();
mRenderThread.cacheManager().trimStaleResources();
}
@@ -71,9 +75,15 @@ void SkiaPipeline::unpinImages() {
mPinnedImages.clear();
}
+void SkiaPipeline::onPrepareTree() {
+ // The only time mVectorDrawables is not empty is if prepare tree was called 2 times without
+ // a renderFrame in the middle.
+ mVectorDrawables.clear();
+}
+
void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) {
+ LayerUpdateQueue* layerUpdateQueue, bool opaque,
+ bool wideColorGamut, const BakedOpRenderer::LightInfo& lightInfo) {
updateLighting(lightGeometry, lightInfo);
ATRACE_NAME("draw layers");
renderVectorDrawableCache();
@@ -81,9 +91,10 @@ void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry
layerUpdateQueue->clear();
}
-void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,
- bool opaque, bool wideColorGamut) {
- // TODO: Handle wide color gamut
+void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque,
+ bool wideColorGamut) {
+ sk_sp<GrContext> cachedContext;
+
// Render all layers that need to be updated, in order.
for (size_t i = 0; i < layers.entries().size(); i++) {
RenderNode* layerNode = layers.entries()[i].renderNode.get();
@@ -101,7 +112,7 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,
const Rect& layerDamage = layers.entries()[i].damage;
- SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
+ SkCanvas* layerCanvas = tryCapture(layerNode->getLayerSurface());
int saveCount = layerCanvas->save();
SkASSERT(saveCount == 1);
@@ -118,35 +129,77 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,
return;
}
+ ATRACE_FORMAT("drawLayer [%s] %.1f x %.1f", layerNode->getName(), bounds.width(),
+ bounds.height());
+
layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false;
layerCanvas->clear(SK_ColorTRANSPARENT);
RenderNodeDrawable root(layerNode, layerCanvas, false);
root.forceDraw(layerCanvas);
layerCanvas->restoreToCount(saveCount);
- layerCanvas->flush();
mLightCenter = savedLightCenter;
+
+ endCapture(layerNode->getLayerSurface());
+
+ // cache the current context so that we can defer flushing it until
+ // either all the layers have been rendered or the context changes
+ GrContext* currentContext = layerNode->getLayerSurface()->getCanvas()->getGrContext();
+ if (cachedContext.get() != currentContext) {
+ if (cachedContext.get()) {
+ ATRACE_NAME("flush layers (context changed)");
+ cachedContext->flush();
+ }
+ cachedContext.reset(SkSafeRef(currentContext));
+ }
}
}
+
+ if (cachedContext.get()) {
+ ATRACE_NAME("flush layers");
+ cachedContext->flush();
+ }
}
-bool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) {
+bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut, ErrorHandler* errorHandler) {
+ // compute the size of the surface (i.e. texture) to be allocated for this layer
+ const int surfaceWidth = ceilf(node->getWidth() / float(LAYER_SIZE)) * LAYER_SIZE;
+ const int surfaceHeight = ceilf(node->getHeight() / float(LAYER_SIZE)) * LAYER_SIZE;
+
SkSurface* layer = node->getLayerSurface();
- if (!layer || layer->width() != node->getWidth() || layer->height() != node->getHeight()) {
- SkImageInfo info = SkImageInfo::MakeN32Premul(node->getWidth(), node->getHeight());
+ if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
+ SkImageInfo info;
+ if (wideColorGamut) {
+ info = SkImageInfo::Make(surfaceWidth, surfaceHeight, kRGBA_F16_SkColorType,
+ kPremul_SkAlphaType);
+ } else {
+ info = SkImageInfo::MakeN32Premul(surfaceWidth, surfaceHeight);
+ }
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkASSERT(mRenderThread.getGrContext() != nullptr);
- // TODO: Handle wide color gamut requests
- node->setLayerSurface(
- SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
- info, 0, &props));
+ node->setLayerSurface(SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
+ SkBudgeted::kYes, info, 0, &props));
if (node->getLayerSurface()) {
// update the transform in window of the layer to reset its origin wrt light source
// position
Matrix4 windowTransform;
damageAccumulator.computeCurrentTransform(&windowTransform);
node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
+ } else {
+ String8 cachesOutput;
+ mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
+ &mRenderThread.renderState());
+ ALOGE("%s", cachesOutput.string());
+ if (errorHandler) {
+ std::ostringstream err;
+ err << "Unable to create layer for " << node->getName();
+ const int maxTextureSize = DeviceInfo::get()->maxTextureSize();
+ err << ", size " << info.width() << "x" << info.height() << " max size "
+ << maxTextureSize << " color type " << (int)info.colorType()
+ << " has context " << (int)(mRenderThread.getGrContext() != nullptr);
+ errorHandler->onError(err.str());
+ }
}
return true;
}
@@ -161,7 +214,8 @@ void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
GrContext* context = thread.getGrContext();
if (context) {
ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
- auto image = bitmap->makeImage();
+ sk_sp<SkColorFilter> colorFilter;
+ auto image = bitmap->makeImage(&colorFilter);
if (image.get() && !bitmap->isHardware()) {
SkImage_pinAsTexture(image.get(), context);
SkImage_unpinAsTexture(image.get(), context);
@@ -169,96 +223,145 @@ void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
}
}
-// Encodes to PNG, unless there is already encoded data, in which case that gets
-// used.
-class PngPixelSerializer : public SkPixelSerializer {
-public:
- bool onUseEncodedData(const void*, size_t) override { return true; }
- SkData* onEncode(const SkPixmap& pixmap) override {
- SkDynamicMemoryWStream buf;
- return SkEncodeImage(&buf, pixmap, SkEncodedImageFormat::kPNG, 100)
- ? buf.detachAsData().release()
- : nullptr;
- }
-};
-
void SkiaPipeline::renderVectorDrawableCache() {
if (!mVectorDrawables.empty()) {
sp<VectorDrawableAtlas> atlas = mRenderThread.cacheManager().acquireVectorDrawableAtlas();
auto grContext = mRenderThread.getGrContext();
atlas->prepareForDraw(grContext);
+ ATRACE_NAME("Update VectorDrawables");
for (auto vd : mVectorDrawables) {
vd->updateCache(atlas, grContext);
}
- grContext->flush();
mVectorDrawables.clear();
}
}
-void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
- const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
- const Rect &contentDrawBounds, sk_sp<SkSurface> surface) {
+class SkiaPipeline::SavePictureProcessor : public TaskProcessor<bool> {
+public:
+ explicit SavePictureProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
+
+ struct SavePictureTask : public Task<bool> {
+ sk_sp<SkData> data;
+ std::string filename;
+ };
+
+ void savePicture(const sk_sp<SkData>& data, const std::string& filename) {
+ sp<SavePictureTask> task(new SavePictureTask());
+ task->data = data;
+ task->filename = filename;
+ TaskProcessor<bool>::add(task);
+ }
- renderVectorDrawableCache();
+ virtual void onProcess(const sp<Task<bool>>& task) override {
+ SavePictureTask* t = static_cast<SavePictureTask*>(task.get());
- // draw all layers up front
- renderLayersImpl(layers, opaque, wideColorGamut);
+ if (0 == access(t->filename.c_str(), F_OK)) {
+ task->setResult(false);
+ return;
+ }
- // initialize the canvas for the current frame
- SkCanvas* canvas = surface->getCanvas();
+ SkFILEWStream stream(t->filename.c_str());
+ if (stream.isValid()) {
+ stream.write(t->data->data(), t->data->size());
+ stream.flush();
+ SkDebugf("SKP Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(),
+ t->filename.c_str());
+ }
- std::unique_ptr<SkPictureRecorder> recorder;
- bool recordingPicture = false;
- char prop[PROPERTY_VALUE_MAX];
- if (skpCaptureEnabled()) {
- property_get("debug.hwui.capture_frame_as_skp", prop, "0");
- recordingPicture = prop[0] != '0' && access(prop, F_OK) != 0;
+ task->setResult(true);
+ }
+};
+
+SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) {
+ if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
+ bool recordingPicture = mCaptureSequence > 0;
+ char prop[PROPERTY_VALUE_MAX] = {'\0'};
+ if (!recordingPicture) {
+ property_get(PROPERTY_CAPTURE_SKP_FILENAME, prop, "0");
+ recordingPicture = prop[0] != '0' &&
+ mCapturedFile != prop; // ensure we capture only once per filename
+ if (recordingPicture) {
+ mCapturedFile = prop;
+ mCaptureSequence = property_get_int32(PROPERTY_CAPTURE_SKP_FRAMES, 1);
+ }
+ }
if (recordingPicture) {
- recorder.reset(new SkPictureRecorder());
- canvas = recorder->beginRecording(surface->width(), surface->height(),
- nullptr, SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
+ mRecorder.reset(new SkPictureRecorder());
+ return mRecorder->beginRecording(surface->width(), surface->height(), nullptr,
+ SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
}
}
+ return surface->getCanvas();
+}
- renderFrameImpl(layers, clip, nodes, opaque, wideColorGamut, contentDrawBounds, canvas);
-
- if (skpCaptureEnabled() && recordingPicture) {
- sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
+void SkiaPipeline::endCapture(SkSurface* surface) {
+ if (CC_UNLIKELY(mRecorder.get())) {
+ sk_sp<SkPicture> picture = mRecorder->finishRecordingAsPicture();
+ surface->getCanvas()->drawPicture(picture);
if (picture->approximateOpCount() > 0) {
- SkFILEWStream stream(prop);
- if (stream.isValid()) {
- PngPixelSerializer serializer;
- picture->serialize(&stream, &serializer);
- stream.flush();
- SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);
+ auto data = picture->serialize();
+
+ // offload saving to file in a different thread
+ if (!mSavePictureProcessor.get()) {
+ TaskManager* taskManager = getTaskManager();
+ mSavePictureProcessor = new SavePictureProcessor(
+ taskManager->canRunTasks() ? taskManager : nullptr);
+ }
+ if (1 == mCaptureSequence) {
+ mSavePictureProcessor->savePicture(data, mCapturedFile);
+ } else {
+ mSavePictureProcessor->savePicture(
+ data,
+ mCapturedFile + "_" + std::to_string(mCaptureSequence));
}
+ mCaptureSequence--;
}
- surface->getCanvas()->drawPicture(picture);
+ mRecorder.reset();
}
+}
+
+void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
+ const std::vector<sp<RenderNode>>& nodes, bool opaque,
+ bool wideColorGamut, const Rect& contentDrawBounds,
+ sk_sp<SkSurface> surface) {
+ renderVectorDrawableCache();
+
+ // draw all layers up front
+ renderLayersImpl(layers, opaque, wideColorGamut);
+
+ // initialize the canvas for the current frame, that might be a recording canvas if SKP
+ // capture is enabled.
+ std::unique_ptr<SkPictureRecorder> recorder;
+ SkCanvas* canvas = tryCapture(surface.get());
+
+ renderFrameImpl(layers, clip, nodes, opaque, wideColorGamut, contentDrawBounds, canvas);
+
+ endCapture(surface.get());
if (CC_UNLIKELY(Properties::debugOverdraw)) {
renderOverdraw(layers, clip, nodes, contentDrawBounds, surface);
}
ATRACE_NAME("flush commands");
- canvas->flush();
+ surface->getCanvas()->flush();
}
namespace {
static Rect nodeBounds(RenderNode& node) {
auto& props = node.properties();
- return Rect(props.getLeft(), props.getTop(),
- props.getRight(), props.getBottom());
+ return Rect(props.getLeft(), props.getTop(), props.getRight(), props.getBottom());
}
}
void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
- const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
- const Rect &contentDrawBounds, SkCanvas* canvas) {
+ const std::vector<sp<RenderNode>>& nodes, bool opaque,
+ bool wideColorGamut, const Rect& contentDrawBounds,
+ SkCanvas* canvas) {
SkAutoCanvasRestore saver(canvas, true);
canvas->androidFramework_setDeviceClipRestriction(clip.roundOut());
- if (!opaque) {
+ // STOPSHIP: Revert, temporary workaround to clear always F16 frame buffer for b/74976293
+ if (!opaque || wideColorGamut) {
canvas->clear(SK_ColorTRANSPARENT);
}
@@ -268,15 +371,18 @@ void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect&
root.draw(canvas);
}
} else if (0 == nodes.size()) {
- //nothing to draw
+ // nothing to draw
} else {
// It there are multiple render nodes, they are laid out as follows:
// #0 - backdrop (content + caption)
// #1 - content (local bounds are at (0,0), will be translated and clipped to backdrop)
// #2 - additional overlay nodes
- // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
- // resizing however it might become partially visible. The following render loop will crop the
- // backdrop against the content and draw the remaining part of it. It will then draw the content
+ // Usually the backdrop cannot be seen since it will be entirely covered by the content.
+ // While
+ // resizing however it might become partially visible. The following render loop will crop
+ // the
+ // backdrop against the content and draw the remaining part of it. It will then draw the
+ // content
// cropped to the backdrop (since that indicates a shrinking of the window).
//
// Additional nodes will be drawn on top with no particular clipping semantics.
@@ -288,29 +394,31 @@ void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect&
// Backdrop bounds in render target space
const Rect backdrop = nodeBounds(*nodes[0]);
- // Bounds that content will fill in render target space (note content node bounds may be bigger)
+ // Bounds that content will fill in render target space (note content node bounds may be
+ // bigger)
Rect content(contentDrawBounds.getWidth(), contentDrawBounds.getHeight());
content.translate(backdrop.left, backdrop.top);
if (!content.contains(backdrop) && !nodes[0]->nothingToDraw()) {
// Content doesn't entirely overlap backdrop, so fill around content (right/bottom)
// Note: in the future, if content doesn't snap to backdrop's left/top, this may need to
- // also fill left/top. Currently, both 2up and freeform position content at the top/left of
+ // also fill left/top. Currently, both 2up and freeform position content at the top/left
+ // of
// the backdrop, so this isn't necessary.
RenderNodeDrawable backdropNode(nodes[0].get(), canvas);
if (content.right < backdrop.right) {
// draw backdrop to right side of content
SkAutoCanvasRestore acr(canvas, true);
- canvas->clipRect(SkRect::MakeLTRB(content.right, backdrop.top,
- backdrop.right, backdrop.bottom));
+ canvas->clipRect(SkRect::MakeLTRB(content.right, backdrop.top, backdrop.right,
+ backdrop.bottom));
backdropNode.draw(canvas);
}
if (content.bottom < backdrop.bottom) {
// draw backdrop to bottom of content
// Note: bottom fill uses content left/right, to avoid overdrawing left/right fill
SkAutoCanvasRestore acr(canvas, true);
- canvas->clipRect(SkRect::MakeLTRB(content.left, content.bottom,
- content.right, backdrop.bottom));
+ canvas->clipRect(SkRect::MakeLTRB(content.left, content.bottom, content.right,
+ backdrop.bottom));
backdropNode.draw(canvas);
}
}
@@ -323,8 +431,9 @@ void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect&
SkAutoCanvasRestore acr(canvas, true);
canvas->translate(dx, dy);
- const SkRect contentLocalClip = SkRect::MakeXYWH(contentDrawBounds.left,
- contentDrawBounds.top, backdrop.getWidth(), backdrop.getHeight());
+ const SkRect contentLocalClip =
+ SkRect::MakeXYWH(contentDrawBounds.left, contentDrawBounds.top,
+ backdrop.getWidth(), backdrop.getHeight());
canvas->clipRect(contentLocalClip);
contentNode.draw(canvas);
} else {
@@ -351,8 +460,8 @@ void SkiaPipeline::dumpResourceCacheUsage() const {
SkString log("Resource Cache Usage:\n");
log.appendf("%8d items out of %d maximum items\n", resources, maxResources);
- log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n",
- bytes, bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f)));
+ log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n", bytes,
+ bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f)));
ALOGD("%s", log.c_str());
}
@@ -365,13 +474,17 @@ void SkiaPipeline::dumpResourceCacheUsage() const {
// (2) Requires premul colors (instead of unpremul).
// (3) Requires RGBA colors (instead of BGRA).
static const uint32_t kOverdrawColors[2][6] = {
- { 0x00000000, 0x00000000, 0x2f2f0000, 0x2f002f00, 0x3f00003f, 0x7f00007f, },
- { 0x00000000, 0x00000000, 0x2f2f0000, 0x4f004f4f, 0x5f50335f, 0x7f00007f, },
+ {
+ 0x00000000, 0x00000000, 0x2f2f0000, 0x2f002f00, 0x3f00003f, 0x7f00007f,
+ },
+ {
+ 0x00000000, 0x00000000, 0x2f2f0000, 0x4f004f4f, 0x5f50335f, 0x7f00007f,
+ },
};
void SkiaPipeline::renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip,
- const std::vector<sp<RenderNode>>& nodes, const Rect &contentDrawBounds,
- sk_sp<SkSurface> surface) {
+ const std::vector<sp<RenderNode>>& nodes,
+ const Rect& contentDrawBounds, sk_sp<SkSurface> surface) {
// Set up the overdraw canvas.
SkImageInfo offscreenInfo = SkImageInfo::MakeA8(surface->width(), surface->height());
sk_sp<SkSurface> offscreen = surface->makeSurface(offscreenInfo);
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 19ffc463c121..38ad9c09a8aa 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -16,10 +16,13 @@
#pragma once
-#include "renderthread/CanvasContext.h"
+#include <SkSurface.h>
#include "FrameBuilder.h"
+#include "hwui/AnimatedImageDrawable.h"
+#include "renderthread/CanvasContext.h"
#include "renderthread/IRenderPipeline.h"
-#include <SkSurface.h>
+
+class SkPictureRecorder;
namespace android {
namespace uirenderer {
@@ -28,7 +31,7 @@ namespace skiapipeline {
class SkiaPipeline : public renderthread::IRenderPipeline {
public:
SkiaPipeline(renderthread::RenderThread& thread);
- virtual ~SkiaPipeline() {}
+ virtual ~SkiaPipeline();
TaskManager* getTaskManager() override;
@@ -37,17 +40,18 @@ public:
bool pinImages(std::vector<SkImage*>& mutableImages) override;
bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; }
void unpinImages() override;
+ void onPrepareTree() override;
void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) override;
+ LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo) override;
- bool createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) override;
+ bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut, ErrorHandler* errorHandler) override;
void renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
- const std::vector< sp<RenderNode> >& nodes, bool opaque, bool wideColorGamut,
- const Rect &contentDrawBounds, sk_sp<SkSurface> surface);
+ const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
+ const Rect& contentDrawBounds, sk_sp<SkSurface> surface);
std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; }
@@ -55,9 +59,7 @@ public:
static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
- static void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque, bool wideColorGamut);
-
- static bool skpCaptureEnabled() { return false; }
+ void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque, bool wideColorGamut);
static float getLightRadius() {
if (CC_UNLIKELY(Properties::overrideLightRadius > 0)) {
@@ -85,7 +87,7 @@ public:
Vector3 adjustedLightCenter = mLightCenter;
if (CC_UNLIKELY(Properties::overrideLightPosY > 0)) {
// negated since this shifts up
- adjustedLightCenter.y = - Properties::overrideLightPosY;
+ adjustedLightCenter.y = -Properties::overrideLightPosY;
}
if (CC_UNLIKELY(Properties::overrideLightPosZ > 0)) {
adjustedLightCenter.z = Properties::overrideLightPosZ;
@@ -96,7 +98,7 @@ public:
}
static void updateLighting(const FrameBuilder::LightGeometry& lightGeometry,
- const BakedOpRenderer::LightInfo& lightInfo) {
+ const BakedOpRenderer::LightInfo& lightInfo) {
mLightRadius = lightGeometry.radius;
mAmbientShadowAlpha = lightInfo.ambientShadowAlpha;
mSpotShadowAlpha = lightInfo.spotShadowAlpha;
@@ -110,29 +112,53 @@ protected:
private:
void renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
- const std::vector< sp<RenderNode> >& nodes, bool opaque, bool wideColorGamut,
- const Rect &contentDrawBounds, SkCanvas* canvas);
+ const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
+ const Rect& contentDrawBounds, SkCanvas* canvas);
/**
* Debugging feature. Draws a semi-transparent overlay on each pixel, indicating
* how many times it has been drawn.
*/
void renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip,
- const std::vector< sp<RenderNode> >& nodes, const Rect &contentDrawBounds,
- sk_sp<SkSurface>);
+ const std::vector<sp<RenderNode>>& nodes, const Rect& contentDrawBounds,
+ sk_sp<SkSurface>);
/**
* Render mVectorDrawables into offscreen buffers.
*/
void renderVectorDrawableCache();
- TaskManager mTaskManager;
+ SkCanvas* tryCapture(SkSurface* surface);
+ void endCapture(SkSurface* surface);
+
std::vector<sk_sp<SkImage>> mPinnedImages;
/**
* populated by prepareTree with dirty VDs
*/
std::vector<VectorDrawableRoot*> mVectorDrawables;
+
+ // Block of properties used only for debugging to record a SkPicture and save it in a file.
+ /**
+ * mCapturedFile is used to enforce we don't capture more than once for a given name (cause
+ * permissions don't allow to reset a property from render thread).
+ */
+ std::string mCapturedFile;
+ /**
+ * mCaptureSequence counts how many frames are left to take in the sequence.
+ */
+ int mCaptureSequence = 0;
+ /**
+ * mSavePictureProcessor is used to run the file saving code in a separate thread.
+ */
+ class SavePictureProcessor;
+ sp<SavePictureProcessor> mSavePictureProcessor;
+ /**
+ * mRecorder holds the current picture recorder. We could store it on the stack to support
+ * parallel tryCapture calls (not really needed).
+ */
+ std::unique_ptr<SkPictureRecorder> mRecorder;
+
static float mLightRadius;
static uint8_t mAmbientShadowAlpha;
static uint8_t mSpotShadowAlpha;
diff --git a/libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp b/libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp
index d97fb372fe0c..492c39f1288c 100644
--- a/libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp
+++ b/libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp
@@ -20,7 +20,7 @@ namespace android {
namespace uirenderer {
void SkiaProfileRenderer::drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) {
+ const SkPaint& paint) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
mCanvas->drawRect(rect, paint);
}
@@ -28,7 +28,7 @@ void SkiaProfileRenderer::drawRect(float left, float top, float right, float bot
void SkiaProfileRenderer::drawRects(const float* rects, int count, const SkPaint& paint) {
for (int index = 0; index + 4 <= count; index += 4) {
SkRect rect = SkRect::MakeLTRB(rects[index + 0], rects[index + 1], rects[index + 2],
- rects[index + 3]);
+ rects[index + 3]);
mCanvas->drawRect(rect, paint);
}
}
diff --git a/libs/hwui/pipeline/skia/SkiaProfileRenderer.h b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
index e6b7f8307379..5ae7d6b0b607 100644
--- a/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
+++ b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
@@ -23,8 +23,7 @@ namespace uirenderer {
class SkiaProfileRenderer : public IProfileRenderer {
public:
- SkiaProfileRenderer(SkCanvas* canvas)
- : mCanvas(canvas) {}
+ SkiaProfileRenderer(SkCanvas* canvas) : mCanvas(canvas) {}
void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
void drawRects(const float* rects, int count, const SkPaint& paint) override;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index a0cce98c8d57..f0da660f17b0 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -16,12 +16,12 @@
#include "SkiaRecordingCanvas.h"
+#include <SkImagePriv.h>
#include "Layer.h"
-#include "RenderNode.h"
#include "LayerDrawable.h"
#include "NinePatchUtils.h"
+#include "RenderNode.h"
#include "pipeline/skia/AnimatedDrawables.h"
-#include <SkImagePriv.h>
namespace android {
namespace uirenderer {
@@ -32,7 +32,7 @@ namespace skiapipeline {
// ----------------------------------------------------------------------------
void SkiaRecordingCanvas::initDisplayList(uirenderer::RenderNode* renderNode, int width,
- int height) {
+ int height) {
mCurrentBarrier = nullptr;
SkASSERT(mDisplayList.get() == nullptr);
@@ -59,17 +59,21 @@ uirenderer::DisplayList* SkiaRecordingCanvas::finishRecording() {
// ----------------------------------------------------------------------------
void SkiaRecordingCanvas::drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
- uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
- uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
- uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) {
+ uirenderer::CanvasPropertyPrimitive* top,
+ uirenderer::CanvasPropertyPrimitive* right,
+ uirenderer::CanvasPropertyPrimitive* bottom,
+ uirenderer::CanvasPropertyPrimitive* rx,
+ uirenderer::CanvasPropertyPrimitive* ry,
+ uirenderer::CanvasPropertyPaint* paint) {
// Destructor of drawables created with allocateDrawable, will be invoked by ~LinearAllocator.
- drawDrawable(mDisplayList->allocateDrawable<AnimatedRoundRect>(left, top, right, bottom,
- rx, ry, paint));
+ drawDrawable(mDisplayList->allocateDrawable<AnimatedRoundRect>(left, top, right, bottom, rx, ry,
+ paint));
}
void SkiaRecordingCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x,
- uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
- uirenderer::CanvasPropertyPaint* paint) {
+ uirenderer::CanvasPropertyPrimitive* y,
+ uirenderer::CanvasPropertyPrimitive* radius,
+ uirenderer::CanvasPropertyPaint* paint) {
drawDrawable(mDisplayList->allocateDrawable<AnimatedCircle>(x, y, radius, paint));
}
@@ -77,24 +81,22 @@ void SkiaRecordingCanvas::insertReorderBarrier(bool enableReorder) {
if (nullptr != mCurrentBarrier) {
// finish off the existing chunk
SkDrawable* drawable =
- mDisplayList->allocateDrawable<EndReorderBarrierDrawable>(
- mCurrentBarrier);
+ mDisplayList->allocateDrawable<EndReorderBarrierDrawable>(mCurrentBarrier);
mCurrentBarrier = nullptr;
drawDrawable(drawable);
}
if (enableReorder) {
mCurrentBarrier = (StartReorderBarrierDrawable*)
- mDisplayList->allocateDrawable<StartReorderBarrierDrawable>(
- mDisplayList.get());
+ mDisplayList->allocateDrawable<StartReorderBarrierDrawable>(
+ mDisplayList.get());
drawDrawable(mCurrentBarrier);
}
}
void SkiaRecordingCanvas::drawLayer(uirenderer::DeferredLayerUpdater* layerUpdater) {
- if (layerUpdater != nullptr && layerUpdater->backingLayer() != nullptr) {
- uirenderer::Layer* layer = layerUpdater->backingLayer();
+ if (layerUpdater != nullptr) {
// Create a ref-counted drawable, which is kept alive by sk_sp in SkLiteDL.
- sk_sp<SkDrawable> drawable(new LayerDrawable(layer));
+ sk_sp<SkDrawable> drawable(new LayerDrawable(layerUpdater));
drawDrawable(drawable.get());
}
}
@@ -114,26 +116,27 @@ void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) {
}
void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor,
- uirenderer::GlFunctorLifecycleListener* listener) {
+ uirenderer::GlFunctorLifecycleListener* listener) {
// Drawable dtor will be invoked when mChildFunctors deque is cleared.
mDisplayList->mChildFunctors.emplace_back(functor, listener, asSkCanvas());
drawDrawable(&mDisplayList->mChildFunctors.back());
}
class VectorDrawable : public SkDrawable {
- public:
- VectorDrawable(VectorDrawableRoot* tree) : mRoot(tree) {}
-
- protected:
- virtual SkRect onGetBounds() override {
- return SkRect::MakeLargest();
- }
- virtual void onDraw(SkCanvas* canvas) override {
- mRoot->draw(canvas);
- }
-
- private:
+public:
+ VectorDrawable(VectorDrawableRoot* tree)
+ : mRoot(tree)
+ , mBounds(tree->stagingProperties()->getBounds()) {}
+
+protected:
+ virtual SkRect onGetBounds() override { return mBounds; }
+ virtual void onDraw(SkCanvas* canvas) override {
+ mRoot->draw(canvas, mBounds);
+ }
+
+private:
sp<VectorDrawableRoot> mRoot;
+ SkRect mBounds;
};
void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
@@ -145,20 +148,12 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
// Recording Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
-inline static const SkPaint* nonAAPaint(const SkPaint* origPaint, SkPaint* tmpPaint) {
- if (origPaint && origPaint->isAntiAlias()) {
- *tmpPaint = *origPaint;
- tmpPaint->setAntiAlias(false);
- return tmpPaint;
- } else {
- return origPaint;
- }
-}
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
- sk_sp<SkImage> image = bitmap.makeImage();
SkPaint tmpPaint;
- mRecorder.drawImage(image, left, top, nonAAPaint(paint, &tmpPaint));
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mRecorder.drawImage(image, left, top, bitmapPaint(paint, &tmpPaint, colorFilter));
// if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
// it is not safe to store a raw SkImage pointer, because the image object will be destroyed
// when this function ends.
@@ -167,38 +162,44 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, cons
}
}
-void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
- const SkPaint* paint) {
+void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
SkAutoCanvasRestore acr(&mRecorder, true);
concat(matrix);
- sk_sp<SkImage> image = hwuiBitmap.makeImage();
+
SkPaint tmpPaint;
- mRecorder.drawImage(image, 0, 0, nonAAPaint(paint, &tmpPaint));
- if (!hwuiBitmap.isImmutable() && image.get() && !image->unique()) {
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mRecorder.drawImage(image, 0, 0, bitmapPaint(paint, &tmpPaint, colorFilter));
+ if (!bitmap.isImmutable() && image.get() && !image->unique()) {
mDisplayList->mMutableImages.push_back(image.get());
}
}
-void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
- float dstBottom, const SkPaint* paint) {
+void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) {
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- sk_sp<SkImage> image = hwuiBitmap.makeImage();
+
SkPaint tmpPaint;
- mRecorder.drawImageRect(image, srcRect, dstRect, nonAAPaint(paint, &tmpPaint));
- if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty()
- && !dstRect.isEmpty()) {
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mRecorder.drawImageRect(image, srcRect, dstRect, bitmapPaint(paint, &tmpPaint, colorFilter),
+ SkCanvas::kFast_SrcRectConstraint);
+ if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
+ !dstRect.isEmpty()) {
mDisplayList->mMutableImages.push_back(image.get());
}
}
-void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
+void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft,
+ float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) {
SkCanvas::Lattice lattice;
- NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
+ NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
- lattice.fFlags = nullptr;
+ lattice.fRectTypes = nullptr;
+ lattice.fColors = nullptr;
int numFlags = 0;
if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) {
// We can expect the framework to give us a color for every distinct rect.
@@ -206,22 +207,43 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch
numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
}
- SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags);
+ SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags);
+ SkAutoSTMalloc<25, SkColor> colors(numFlags);
if (numFlags > 0) {
- NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk);
+ NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
}
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- sk_sp<SkImage> image = hwuiBitmap.makeImage();
SkPaint tmpPaint;
- mRecorder.drawImageLattice(image.get(), lattice, dst, nonAAPaint(paint, &tmpPaint));
- if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ const SkPaint* filteredPaint = bitmapPaint(paint, &tmpPaint, colorFilter);
+ // Besides kNone, the other three SkFilterQualities are treated the same. And Android's
+ // Java API only supports kLow and kNone anyway.
+ if (!filteredPaint || filteredPaint->getFilterQuality() == kNone_SkFilterQuality) {
+ if (filteredPaint != &tmpPaint) {
+ if (paint) {
+ tmpPaint = *paint;
+ }
+ filteredPaint = &tmpPaint;
+ }
+ tmpPaint.setFilterQuality(kLow_SkFilterQuality);
+ }
+
+ mRecorder.drawImageLattice(image.get(), lattice, dst, filteredPaint);
+ if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
mDisplayList->mMutableImages.push_back(image.get());
}
}
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+double SkiaRecordingCanvas::drawAnimatedImage(AnimatedImageDrawable* animatedImage) {
+ drawDrawable(animatedImage);
+ mDisplayList->mAnimatedImages.push_back(animatedImage);
+ return 0;
+}
+
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 10829f87efb9..93807a5476e6 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -15,10 +15,10 @@
*/
#pragma once
+#include <SkLiteRecorder.h>
+#include "ReorderBarrierDrawables.h"
#include "SkiaCanvas.h"
#include "SkiaDisplayList.h"
-#include "ReorderBarrierDrawables.h"
-#include <SkLiteRecorder.h>
namespace android {
namespace uirenderer {
@@ -29,7 +29,7 @@ namespace skiapipeline {
* SkLiteRecorder and a SkiaDisplayList.
*/
class SkiaRecordingCanvas : public SkiaCanvas {
- public:
+public:
explicit SkiaRecordingCanvas(uirenderer::RenderNode* renderNode, int width, int height) {
initDisplayList(renderNode, width, height);
}
@@ -39,31 +39,33 @@ class SkiaRecordingCanvas : public SkiaCanvas {
}
virtual void resetRecording(int width, int height,
- uirenderer::RenderNode* renderNode) override {
+ uirenderer::RenderNode* renderNode) override {
initDisplayList(renderNode, width, height);
}
virtual uirenderer::DisplayList* finishRecording() override;
- virtual void drawBitmap(Bitmap& bitmap, float left, float top,
- const SkPaint* paint) override;
- virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix,
- const SkPaint* paint) override;
- virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) override;
+ virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override;
+ virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override;
+ virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) override;
virtual void drawNinePatch(Bitmap& hwuiBitmap, const android::Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkPaint* paint) override;
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) override;
+ virtual double drawAnimatedImage(AnimatedImageDrawable* animatedImage) override;
virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
- uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
- uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
- uirenderer::CanvasPropertyPrimitive* ry,
- uirenderer::CanvasPropertyPaint* paint) override;
+ uirenderer::CanvasPropertyPrimitive* top,
+ uirenderer::CanvasPropertyPrimitive* right,
+ uirenderer::CanvasPropertyPrimitive* bottom,
+ uirenderer::CanvasPropertyPrimitive* rx,
+ uirenderer::CanvasPropertyPrimitive* ry,
+ uirenderer::CanvasPropertyPaint* paint) override;
virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x,
- uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
- uirenderer::CanvasPropertyPaint* paint) override;
+ uirenderer::CanvasPropertyPrimitive* y,
+ uirenderer::CanvasPropertyPrimitive* radius,
+ uirenderer::CanvasPropertyPaint* paint) override;
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
@@ -86,8 +88,47 @@ private:
* @param height used to calculate recording bounds.
*/
void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
+
+ inline static const SkPaint* bitmapPaint(const SkPaint* origPaint, SkPaint* tmpPaint,
+ sk_sp<SkColorFilter> colorSpaceFilter) {
+ bool fixBlending = false;
+ bool fixAA = false;
+ if (origPaint) {
+ // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and
+ // older.
+ fixBlending = sApiLevel <= 27 && origPaint->getBlendMode() == SkBlendMode::kClear;
+ fixAA = origPaint->isAntiAlias();
+ }
+
+ if (fixBlending || fixAA || colorSpaceFilter) {
+ if (origPaint) {
+ *tmpPaint = *origPaint;
+ }
+
+ if (fixBlending) {
+ tmpPaint->setBlendMode(SkBlendMode::kDstOut);
+ }
+
+ if (colorSpaceFilter) {
+ if (tmpPaint->getColorFilter()) {
+ tmpPaint->setColorFilter(SkColorFilter::MakeComposeFilter(
+ tmpPaint->refColorFilter(), colorSpaceFilter));
+ } else {
+ tmpPaint->setColorFilter(colorSpaceFilter);
+ }
+ LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
+ }
+
+ // disabling AA on bitmap draws matches legacy HWUI behavior
+ tmpPaint->setAntiAlias(false);
+ return tmpPaint;
+ } else {
+ return origPaint;
+ }
+ }
+
};
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace skiapipeline
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index e1ef71f7d3ab..5825060f902a 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -17,12 +17,12 @@
#include "SkiaVulkanPipeline.h"
#include "DeferredLayerUpdater.h"
-#include "renderthread/Frame.h"
#include "Readback.h"
-#include "renderstate/RenderState.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
#include "VkLayer.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/Frame.h"
#include <SkSurface.h>
#include <SkTypes.h>
@@ -41,8 +41,7 @@ namespace uirenderer {
namespace skiapipeline {
SkiaVulkanPipeline::SkiaVulkanPipeline(renderthread::RenderThread& thread)
- : SkiaPipeline(thread)
- , mVkManager(thread.vulkanManager()) {}
+ : SkiaPipeline(thread), mVkManager(thread.vulkanManager()) {}
MakeCurrentResult SkiaVulkanPipeline::makeCurrent() {
return MakeCurrentResult::AlreadyCurrent;
@@ -50,7 +49,7 @@ MakeCurrentResult SkiaVulkanPipeline::makeCurrent() {
Frame SkiaVulkanPipeline::getFrame() {
LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
- "drawRenderNode called on a context with no surface!");
+ "drawRenderNode called on a context with no surface!");
SkSurface* backBuffer = mVkManager.getBackbufferSurface(mVkSurface);
if (backBuffer == nullptr) {
@@ -62,27 +61,25 @@ Frame SkiaVulkanPipeline::getFrame() {
return frame;
}
-bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty,
- const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector<sp<RenderNode>>& renderNodes,
- FrameInfoVisualizer* profiler) {
-
+bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
+ bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) {
sk_sp<SkSurface> backBuffer = mVkSurface->getBackBufferSurface();
if (backBuffer.get() == nullptr) {
return false;
}
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
- renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, wideColorGamut,
- contentDrawBounds, backBuffer);
+ renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, wideColorGamut, contentDrawBounds,
+ backBuffer);
layerUpdateQueue->clear();
// Draw visual debugging features
- if (CC_UNLIKELY(Properties::showDirtyRegions
- || ProfileType::None != Properties::getProfileType())) {
+ if (CC_UNLIKELY(Properties::showDirtyRegions ||
+ ProfileType::None != Properties::getProfileType())) {
SkCanvas* profileCanvas = backBuffer->getCanvas();
SkiaProfileRenderer profileRenderer(profileCanvas);
profiler->draw(profileRenderer);
@@ -97,9 +94,8 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty,
return true;
}
-bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew,
- const SkRect& screenDirty, FrameInfo* currentFrameInfo, bool* requireSwap) {
-
+bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
+ FrameInfo* currentFrameInfo, bool* requireSwap) {
*requireSwap = drew;
// Even if we decided to cancel the frame, from the perspective of jank
@@ -119,7 +115,8 @@ bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bi
}
static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
- SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
+ sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode,
+ bool blend) {
return new VkLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
}
@@ -129,11 +126,10 @@ DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::Vulkan);
}
-void SkiaVulkanPipeline::onStop() {
-}
+void SkiaVulkanPipeline::onStop() {}
bool SkiaVulkanPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
- ColorMode colorMode) {
+ ColorMode colorMode) {
if (mVkSurface) {
mVkManager.destroySurface(mVkSurface);
mVkSurface = nullptr;
@@ -162,16 +158,15 @@ void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* func
}
sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
- SkBitmap& skBitmap) {
- //TODO: implement this function for Vulkan pipeline
- //code below is a hack to avoid crashing because of missing HW Bitmap support
- sp<GraphicBuffer> buffer = new GraphicBuffer(skBitmap.info().width(), skBitmap.info().height(),
- PIXEL_FORMAT_RGBA_8888,
- GraphicBuffer::USAGE_HW_TEXTURE |
- GraphicBuffer::USAGE_SW_WRITE_NEVER |
- GraphicBuffer::USAGE_SW_READ_NEVER,
- std::string("SkiaVulkanPipeline::allocateHardwareBitmap pid [")
- + std::to_string(getpid()) + "]");
+ SkBitmap& skBitmap) {
+ // TODO: implement this function for Vulkan pipeline
+ // code below is a hack to avoid crashing because of missing HW Bitmap support
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ skBitmap.info().width(), skBitmap.info().height(), PIXEL_FORMAT_RGBA_8888,
+ GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
+ GraphicBuffer::USAGE_SW_READ_NEVER,
+ std::string("SkiaVulkanPipeline::allocateHardwareBitmap pid [") +
+ std::to_string(getpid()) + "]");
status_t error = buffer->initCheck();
if (error < 0) {
ALOGW("SkiaVulkanPipeline::allocateHardwareBitmap() failed in GraphicBuffer.create()");
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 263206d97571..03b4c79f2beb 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -31,25 +31,24 @@ public:
renderthread::MakeCurrentResult makeCurrent() override;
renderthread::Frame getFrame() override;
bool draw(const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) override;
+ const FrameBuilder::LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+ const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode> >& renderNodes,
+ FrameInfoVisualizer* profiler) override;
bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) override;
+ FrameInfo* currentFrameInfo, bool* requireSwap) override;
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
- renderthread::ColorMode colorMode) override;
+ renderthread::ColorMode colorMode) override;
void onStop() override;
bool isSurfaceReady() override;
bool isContextReady() override;
static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
- SkBitmap& skBitmap);
+ SkBitmap& skBitmap);
private:
renderthread::VulkanManager& mVkManager;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanReadback.h b/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
new file mode 100644
index 000000000000..65b89d617f7b
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Readback.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaVulkanReadback : public Readback {
+public:
+ SkiaVulkanReadback(renderthread::RenderThread& thread) : Readback(thread) {}
+
+ virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
+ SkBitmap* bitmap) override {
+ //TODO: implement Vulkan readback.
+ return CopyResult::UnknownError;
+ }
+
+ virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
+ SkBitmap* bitmap) override {
+ //TODO: implement Vulkan readback.
+ return CopyResult::UnknownError;
+ }
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp b/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp
index 437653a8dfa8..8fb621d24866 100644
--- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp
+++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp
@@ -19,8 +19,9 @@
#include <GrRectanizer_pow2.h>
#include <SkCanvas.h>
#include <cmath>
-#include "utils/TraceUtils.h"
#include "renderthread/RenderProxy.h"
+#include "renderthread/RenderThread.h"
+#include "utils/TraceUtils.h"
namespace android {
namespace uirenderer {
@@ -29,8 +30,7 @@ namespace skiapipeline {
VectorDrawableAtlas::VectorDrawableAtlas(size_t surfaceArea, StorageMode storageMode)
: mWidth((int)std::sqrt(surfaceArea))
, mHeight((int)std::sqrt(surfaceArea))
- , mStorageMode(storageMode) {
-}
+ , mStorageMode(storageMode) {}
void VectorDrawableAtlas::prepareForDraw(GrContext* context) {
if (StorageMode::allowSharedSurface == mStorageMode) {
@@ -54,8 +54,8 @@ void VectorDrawableAtlas::prepareForDraw(GrContext* context) {
#define MAX_UNUSED_RATIO 2.0f
bool VectorDrawableAtlas::isFragmented() {
- return mConsecutiveFailures > MAX_CONSECUTIVE_FAILURES
- && mPixelUsedByVDs*MAX_UNUSED_RATIO < mPixelAllocated;
+ return mConsecutiveFailures > MAX_CONSECUTIVE_FAILURES &&
+ mPixelUsedByVDs * MAX_UNUSED_RATIO < mPixelAllocated;
}
void VectorDrawableAtlas::repackIfNeeded(GrContext* context) {
@@ -68,9 +68,9 @@ void VectorDrawableAtlas::repackIfNeeded(GrContext* context) {
}
// compare to CacheEntry objects based on VD area.
-bool VectorDrawableAtlas::compareCacheEntry(const CacheEntry& first, const CacheEntry& second)
-{
- return first.VDrect.width()*first.VDrect.height() < second.VDrect.width()*second.VDrect.height();
+bool VectorDrawableAtlas::compareCacheEntry(const CacheEntry& first, const CacheEntry& second) {
+ return first.VDrect.width() * first.VDrect.height() <
+ second.VDrect.width() * second.VDrect.height();
}
void VectorDrawableAtlas::repack(GrContext* context) {
@@ -87,7 +87,7 @@ void VectorDrawableAtlas::repack(GrContext* context) {
mRectanizer = std::make_unique<GrRectanizerPow2>(mWidth, mHeight);
} else {
if (!mSurface) {
- return; //nothing to repack
+ return; // nothing to repack
}
mRectanizer.reset();
}
@@ -105,20 +105,20 @@ void VectorDrawableAtlas::repack(GrContext* context) {
for (CacheEntry& entry : mRects) {
SkRect currentVDRect = entry.VDrect;
- SkImage* sourceImage; //copy either from the atlas or from a standalone surface
+ SkImage* sourceImage; // copy either from the atlas or from a standalone surface
if (entry.surface) {
if (!fitInAtlas(currentVDRect.width(), currentVDRect.height())) {
- continue; //don't even try to repack huge VD
+ continue; // don't even try to repack huge VD
}
sourceImage = entry.surface->makeImageSnapshot().get();
} else {
sourceImage = sourceImageAtlas;
}
- size_t VDRectArea = currentVDRect.width()*currentVDRect.height();
+ size_t VDRectArea = currentVDRect.width() * currentVDRect.height();
SkIPoint16 pos;
if (canvas && mRectanizer->addRect(currentVDRect.width(), currentVDRect.height(), &pos)) {
- SkRect newRect = SkRect::MakeXYWH(pos.fX, pos.fY, currentVDRect.width(),
- currentVDRect.height());
+ SkRect newRect =
+ SkRect::MakeXYWH(pos.fX, pos.fY, currentVDRect.width(), currentVDRect.height());
canvas->drawImageRect(sourceImage, currentVDRect, newRect, nullptr);
entry.VDrect = newRect;
entry.rect = newRect;
@@ -133,8 +133,7 @@ void VectorDrawableAtlas::repack(GrContext* context) {
if (!entry.surface) {
// A rectangle moved from an atlas to a standalone surface.
mPixelUsedByVDs -= VDRectArea;
- SkRect newRect = SkRect::MakeWH(currentVDRect.width(),
- currentVDRect.height());
+ SkRect newRect = SkRect::MakeWH(currentVDRect.width(), currentVDRect.height());
entry.surface = createSurface(newRect.width(), newRect.height(), context);
auto tempCanvas = entry.surface->getCanvas();
tempCanvas->clear(SK_ColorTRANSPARENT);
@@ -157,7 +156,7 @@ AtlasEntry VectorDrawableAtlas::requestNewEntry(int width, int height, GrContext
}
if (mSurface) {
- const size_t area = width*height;
+ const size_t area = width * height;
// Use a rectanizer to allocate unused space from the atlas surface.
bool notTooBig = fitInAtlas(width, height);
@@ -228,15 +227,24 @@ AtlasEntry VectorDrawableAtlas::getEntry(AtlasKey atlasKey) {
void VectorDrawableAtlas::releaseEntry(AtlasKey atlasKey) {
if (INVALID_ATLAS_KEY != atlasKey) {
+ if (!renderthread::RenderThread::isCurrent()) {
+ {
+ AutoMutex _lock(mReleaseKeyLock);
+ mKeysForRelease.push_back(atlasKey);
+ }
+ // invoke releaseEntry on the renderthread
+ renderthread::RenderProxy::releaseVDAtlasEntries();
+ return;
+ }
CacheEntry* entry = reinterpret_cast<CacheEntry*>(atlasKey);
if (!entry->surface) {
// Store freed atlas rectangles in "mFreeRects" and try to reuse them later, when atlas
// is full.
SkRect& removedRect = entry->rect;
- size_t rectArea = removedRect.width()*removedRect.height();
+ size_t rectArea = removedRect.width() * removedRect.height();
mFreeRects.emplace(rectArea, removedRect);
SkRect& removedVDRect = entry->VDrect;
- size_t VDRectArea = removedVDRect.width()*removedVDRect.height();
+ size_t VDRectArea = removedVDRect.width() * removedVDRect.height();
mPixelUsedByVDs -= VDRectArea;
mConsecutiveFailures = 0;
}
@@ -245,6 +253,14 @@ void VectorDrawableAtlas::releaseEntry(AtlasKey atlasKey) {
}
}
+void VectorDrawableAtlas::delayedReleaseEntries() {
+ AutoMutex _lock(mReleaseKeyLock);
+ for (auto key : mKeysForRelease) {
+ releaseEntry(key);
+ }
+ mKeysForRelease.clear();
+}
+
sk_sp<SkSurface> VectorDrawableAtlas::createSurface(int width, int height, GrContext* context) {
#ifndef ANDROID_ENABLE_LINEAR_BLENDING
sk_sp<SkColorSpace> colorSpace = nullptr;
@@ -252,7 +268,10 @@ sk_sp<SkSurface> VectorDrawableAtlas::createSurface(int width, int height, GrCon
sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
#endif
SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace);
- return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info);
+ // This must have a top-left origin so that calls to surface->canvas->writePixels
+ // performs a basic texture upload instead of a more complex drawing operation
+ return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0, kTopLeft_GrSurfaceOrigin,
+ nullptr);
}
void VectorDrawableAtlas::setStorageMode(StorageMode mode) {
diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
index 496c55742748..74e48cea2a87 100644
--- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
+++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
@@ -16,11 +16,12 @@
#pragma once
-#include <map>
#include <SkSurface.h>
#include <utils/FatVector.h>
#include <utils/RefBase.h>
+#include <utils/Thread.h>
#include <list>
+#include <map>
class GrRectanizer;
@@ -54,18 +55,15 @@ struct AtlasEntry {
* When a VectorDrawable is deleted, it invokes VectorDrawableAtlas::releaseEntry, which is keeping
* track of free spaces and allow to reuse the surface for another VD.
*/
- //TODO: Check if not using atlas for AnimatedVD is more efficient.
- //TODO: For low memory situations, when there are no paint effects in VD, we may render without an
- //TODO: offscreen surface.
+// TODO: Check if not using atlas for AnimatedVD is more efficient.
+// TODO: For low memory situations, when there are no paint effects in VD, we may render without an
+// TODO: offscreen surface.
class VectorDrawableAtlas : public virtual RefBase {
public:
- enum class StorageMode {
- allowSharedSurface,
- disallowSharedSurface
- };
+ enum class StorageMode { allowSharedSurface, disallowSharedSurface };
VectorDrawableAtlas(size_t surfaceArea,
- StorageMode storageMode = StorageMode::allowSharedSurface);
+ StorageMode storageMode = StorageMode::allowSharedSurface);
/**
* "prepareForDraw" may allocate a new surface if needed. It may schedule to repack the
@@ -103,19 +101,24 @@ public:
/**
* "releaseEntry" is invoked when a VectorDrawable is deleted. Passing a non-existing "atlasKey"
- * is causing an undefined behaviour.
+ * is causing an undefined behaviour. This is the only function in the class that can be
+ * invoked from any thread. It will marshal internally to render thread if needed.
*/
void releaseEntry(AtlasKey atlasKey);
void setStorageMode(StorageMode mode);
+ /**
+ * "delayedReleaseEntries" is indirectly invoked by "releaseEntry", when "releaseEntry" is
+ * invoked from a non render thread.
+ */
+ void delayedReleaseEntries();
+
private:
struct CacheEntry {
CacheEntry(const SkRect& newVDrect, const SkRect& newRect,
- const sk_sp<SkSurface>& newSurface)
- : VDrect(newVDrect)
- , rect(newRect)
- , surface(newSurface) { }
+ const sk_sp<SkSurface>& newSurface)
+ : VDrect(newVDrect), rect(newRect), surface(newSurface) {}
/**
* size and position of VectorDrawable into the atlas or in "this.surface"
@@ -182,10 +185,21 @@ private:
*/
StorageMode mStorageMode;
+ /**
+ * mKeysForRelease is used by releaseEntry implementation to pass atlas keys from an arbitrary
+ * calling thread to the render thread.
+ */
+ std::vector<AtlasKey> mKeysForRelease;
+
+ /**
+ * A lock used to protect access to mKeysForRelease.
+ */
+ Mutex mReleaseKeyLock;
+
sk_sp<SkSurface> createSurface(int width, int height, GrContext* context);
inline bool fitInAtlas(int width, int height) {
- return 2*width < mWidth && 2*height < mHeight;
+ return 2 * width < mWidth && 2 * height < mHeight;
}
void repack(GrContext* context);
diff --git a/libs/hwui/private/hwui/DrawGlInfo.h b/libs/hwui/private/hwui/DrawGlInfo.h
index f57851322716..efa9da27199d 100644
--- a/libs/hwui/private/hwui/DrawGlInfo.h
+++ b/libs/hwui/private/hwui/DrawGlInfo.h
@@ -81,9 +81,9 @@ struct DrawGlInfo {
// commands are issued.
kStatusDrew = 0x4
};
-}; // struct DrawGlInfo
+}; // struct DrawGlInfo
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_DRAW_GL_INFO_H
+#endif // ANDROID_HWUI_DRAW_GL_INFO_H
diff --git a/libs/hwui/protos/ProtoHelpers.h b/libs/hwui/protos/ProtoHelpers.h
index 832e31200eb6..833c77f2b8cb 100644
--- a/libs/hwui/protos/ProtoHelpers.h
+++ b/libs/hwui/protos/ProtoHelpers.h
@@ -35,7 +35,7 @@ void set(std::string* dest, const SkPath& src) {
src.writeToMemory(&*dest->begin());
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
-#endif // PROTOHELPERS_H
+#endif // PROTOHELPERS_H
diff --git a/libs/hwui/protos/graphicsstats.proto b/libs/hwui/protos/graphicsstats.proto
new file mode 100644
index 000000000000..1226d44ceb85
--- /dev/null
+++ b/libs/hwui/protos/graphicsstats.proto
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package android.uirenderer.protos;
+
+option optimize_for = LITE_RUNTIME;
+
+// frameworks/base/core/proto/android/service/graphicsstats.proto is based on
+// this proto. Please only make valid protobuf changes to these messages, and
+// keep the other file in sync with this one.
+
+message GraphicsStatsServiceDumpProto {
+ repeated GraphicsStatsProto stats = 1;
+}
+
+message GraphicsStatsProto {
+ // The package name of the app
+ optional string package_name = 1;
+
+ // The version code of the app
+ optional int64 version_code = 2;
+
+ // The start & end timestamps in UTC as
+ // milliseconds since January 1, 1970
+ // Compatible with java.util.Date#setTime()
+ optional int64 stats_start = 3;
+ optional int64 stats_end = 4;
+
+ // The aggregated statistics for the package
+ optional GraphicsStatsJankSummaryProto summary = 5;
+
+ // The frame time histogram for the package
+ repeated GraphicsStatsHistogramBucketProto histogram = 6;
+}
+
+message GraphicsStatsJankSummaryProto {
+ // Distinct frame count.
+ optional int32 total_frames = 1;
+
+ // Number of frames with slow render time. Frames are considered janky if
+ // they took more than a vsync interval (typically 16.667ms) to be rendered.
+ optional int32 janky_frames = 2;
+
+ // Number of "missed vsync" events.
+ optional int32 missed_vsync_count = 3;
+
+ // Number of frames in triple-buffering scenario (high input latency)
+ optional int32 high_input_latency_count = 4;
+
+ // Number of "slow UI thread" events.
+ optional int32 slow_ui_thread_count = 5;
+
+ // Number of "slow bitmap upload" events.
+ optional int32 slow_bitmap_upload_count = 6;
+
+ // Number of "slow draw" events.
+ optional int32 slow_draw_count = 7;
+
+ // Number of frames that missed their deadline (aka, visibly janked)
+ optional int32 missed_deadline_count = 8;
+}
+
+message GraphicsStatsHistogramBucketProto {
+ // Lower bound of render time in milliseconds.
+ optional int32 render_millis = 1;
+ // Number of frames in the bucket.
+ optional int32 frame_count = 2;
+}
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index b1ca4a248a80..5bef01c0ec3c 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -52,49 +52,42 @@ static_assert(17 == static_cast<int>(SkBlendMode::kLighten), "SkBlendMode enums
// In this array, the index of each Blender equals the value of the first
// entry. For instance, gBlends[1] == gBlends[SkBlendMode::kSrc]
-const Blender kBlends[] = {
- { SkBlendMode::kClear, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kSrc, GL_ONE, GL_ZERO },
- { SkBlendMode::kDst, GL_ZERO, GL_ONE },
- { SkBlendMode::kSrcOver, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kDstOver, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
- { SkBlendMode::kSrcIn, GL_DST_ALPHA, GL_ZERO },
- { SkBlendMode::kDstIn, GL_ZERO, GL_SRC_ALPHA },
- { SkBlendMode::kSrcOut, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
- { SkBlendMode::kDstOut, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kSrcATop, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kDstATop, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
- { SkBlendMode::kXor, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kPlus, GL_ONE, GL_ONE },
- { SkBlendMode::kModulate, GL_ZERO, GL_SRC_COLOR },
- { SkBlendMode::kScreen, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
-};
+const Blender kBlends[] = {{SkBlendMode::kClear, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kSrc, GL_ONE, GL_ZERO},
+ {SkBlendMode::kDst, GL_ZERO, GL_ONE},
+ {SkBlendMode::kSrcOver, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kDstOver, GL_ONE_MINUS_DST_ALPHA, GL_ONE},
+ {SkBlendMode::kSrcIn, GL_DST_ALPHA, GL_ZERO},
+ {SkBlendMode::kDstIn, GL_ZERO, GL_SRC_ALPHA},
+ {SkBlendMode::kSrcOut, GL_ONE_MINUS_DST_ALPHA, GL_ZERO},
+ {SkBlendMode::kDstOut, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kSrcATop, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kDstATop, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA},
+ {SkBlendMode::kXor, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kPlus, GL_ONE, GL_ONE},
+ {SkBlendMode::kModulate, GL_ZERO, GL_SRC_COLOR},
+ {SkBlendMode::kScreen, GL_ONE, GL_ONE_MINUS_SRC_COLOR}};
// This array contains the swapped version of each SkBlendMode. For instance
// this array's SrcOver blending mode is actually DstOver. You can refer to
// createLayer() for more information on the purpose of this array.
-const Blender kBlendsSwap[] = {
- { SkBlendMode::kClear, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
- { SkBlendMode::kSrc, GL_ZERO, GL_ONE },
- { SkBlendMode::kDst, GL_ONE, GL_ZERO },
- { SkBlendMode::kSrcOver, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
- { SkBlendMode::kDstOver, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kSrcIn, GL_ZERO, GL_SRC_ALPHA },
- { SkBlendMode::kDstIn, GL_DST_ALPHA, GL_ZERO },
- { SkBlendMode::kSrcOut, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kDstOut, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
- { SkBlendMode::kSrcATop, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
- { SkBlendMode::kDstATop, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kXor, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
- { SkBlendMode::kPlus, GL_ONE, GL_ONE },
- { SkBlendMode::kModulate, GL_DST_COLOR, GL_ZERO },
- { SkBlendMode::kScreen, GL_ONE_MINUS_DST_COLOR, GL_ONE }
-};
+const Blender kBlendsSwap[] = {{SkBlendMode::kClear, GL_ONE_MINUS_DST_ALPHA, GL_ZERO},
+ {SkBlendMode::kSrc, GL_ZERO, GL_ONE},
+ {SkBlendMode::kDst, GL_ONE, GL_ZERO},
+ {SkBlendMode::kSrcOver, GL_ONE_MINUS_DST_ALPHA, GL_ONE},
+ {SkBlendMode::kDstOver, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kSrcIn, GL_ZERO, GL_SRC_ALPHA},
+ {SkBlendMode::kDstIn, GL_DST_ALPHA, GL_ZERO},
+ {SkBlendMode::kSrcOut, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kDstOut, GL_ONE_MINUS_DST_ALPHA, GL_ZERO},
+ {SkBlendMode::kSrcATop, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA},
+ {SkBlendMode::kDstATop, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kXor, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
+ {SkBlendMode::kPlus, GL_ONE, GL_ONE},
+ {SkBlendMode::kModulate, GL_DST_COLOR, GL_ZERO},
+ {SkBlendMode::kScreen, GL_ONE_MINUS_DST_COLOR, GL_ONE}};
-Blend::Blend()
- : mEnabled(false)
- , mSrcMode(GL_ZERO)
- , mDstMode(GL_ZERO) {
+Blend::Blend() : mEnabled(false), mSrcMode(GL_ZERO), mDstMode(GL_ZERO) {
// gl blending off by default
}
@@ -145,4 +138,3 @@ void Blend::dump() {
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/renderstate/Blend.h b/libs/hwui/renderstate/Blend.h
index a9de24631340..7e559bace3f2 100644
--- a/libs/hwui/renderstate/Blend.h
+++ b/libs/hwui/renderstate/Blend.h
@@ -28,6 +28,7 @@ namespace uirenderer {
class Blend {
friend class RenderState;
+
public:
// dictates whether to swap src/dst
enum class ModeOrderSwap {
@@ -36,19 +37,18 @@ public:
};
void syncEnabled();
- static void getFactors(SkBlendMode mode, ModeOrderSwap modeUsage,
- GLenum* outSrc, GLenum* outDst);
+ static void getFactors(SkBlendMode mode, ModeOrderSwap modeUsage, GLenum* outSrc,
+ GLenum* outDst);
void setFactors(GLenum src, GLenum dst);
- bool getEnabled() {
- return mEnabled;
- }
+ bool getEnabled() { return mEnabled; }
void getFactors(GLenum* src, GLenum* dst) {
*src = mSrcMode;
*dst = mDstMode;
}
void dump();
+
private:
Blend();
void invalidate();
@@ -60,4 +60,4 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-#endif // RENDERSTATE_BLEND_H
+#endif // RENDERSTATE_BLEND_H
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index 6d0293695412..4f6c49e67b99 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -38,12 +38,12 @@ MeshState::MeshState()
for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
uint16_t quad = i * 4;
int index = i * 6;
- regionIndices[index ] = quad; // top-left
- regionIndices[index + 1] = quad + 1; // top-right
- regionIndices[index + 2] = quad + 2; // bottom-left
- regionIndices[index + 3] = quad + 2; // bottom-left
- regionIndices[index + 4] = quad + 1; // top-right
- regionIndices[index + 5] = quad + 3; // bottom-right
+ regionIndices[index] = quad; // top-left
+ regionIndices[index + 1] = quad + 1; // top-right
+ regionIndices[index + 2] = quad + 2; // bottom-left
+ regionIndices[index + 3] = quad + 2; // bottom-left
+ regionIndices[index + 4] = quad + 1; // top-right
+ regionIndices[index + 5] = quad + 3; // bottom-right
}
glGenBuffers(1, &mQuadListIndices);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices);
@@ -65,10 +65,10 @@ MeshState::~MeshState() {
void MeshState::dump() {
ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer);
ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer);
- ALOGD("MeshState vertices: vertex data %p, stride %d",
- mCurrentPositionPointer, mCurrentPositionStride);
- ALOGD("MeshState texCoord: data %p, stride %d",
- mCurrentTexCoordsPointer, mCurrentTexCoordsStride);
+ ALOGD("MeshState vertices: vertex data %p, stride %d", mCurrentPositionPointer,
+ mCurrentPositionStride);
+ ALOGD("MeshState texCoord: data %p, stride %d", mCurrentTexCoordsPointer,
+ mCurrentTexCoordsStride);
}
///////////////////////////////////////////////////////////////////////////////
@@ -89,8 +89,8 @@ void MeshState::unbindMeshBuffer() {
return bindMeshBuffer(0);
}
-void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size,
- const void* data, GLenum usage) {
+void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, const void* data,
+ GLenum usage) {
if (!*buffer) {
glGenBuffers(1, buffer);
}
@@ -98,8 +98,8 @@ void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size,
glBufferData(GL_ARRAY_BUFFER, size, data, usage);
}
-void MeshState::updateMeshBufferSubData(GLuint buffer, GLintptr offset,
- GLsizeiptr size, const void* data) {
+void MeshState::updateMeshBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size,
+ const void* data) {
bindMeshBuffer(buffer);
glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
}
@@ -119,9 +119,8 @@ void MeshState::deleteMeshBuffer(GLuint buffer) {
void MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride) {
// update pos coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
- if (mCurrentBuffer == 0
- || vertices != mCurrentPositionPointer
- || stride != mCurrentPositionStride) {
+ if (mCurrentBuffer == 0 || vertices != mCurrentPositionPointer ||
+ stride != mCurrentPositionStride) {
glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
mCurrentPositionPointer = vertices;
mCurrentPositionStride = stride;
@@ -130,9 +129,8 @@ void MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride
void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) {
// update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
- if (mCurrentBuffer == 0
- || vertices != mCurrentTexCoordsPointer
- || stride != mCurrentTexCoordsStride) {
+ if (mCurrentBuffer == 0 || vertices != mCurrentTexCoordsPointer ||
+ stride != mCurrentTexCoordsStride) {
glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
mCurrentTexCoordsPointer = vertices;
mCurrentTexCoordsStride = stride;
@@ -179,4 +177,3 @@ void MeshState::unbindIndicesBuffer() {
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
index 17ad4622e44a..95faf1ebfb02 100644
--- a/libs/hwui/renderstate/MeshState.h
+++ b/libs/hwui/renderstate/MeshState.h
@@ -33,10 +33,7 @@ const uint32_t kMaxNumberOfQuads = 2048;
// This array is never used directly but used as a memcpy source in the
// OpenGLRenderer constructor
const TextureVertex kUnitQuadVertices[] = {
- { 0, 0, 0, 0 },
- { 1, 0, 1, 0 },
- { 0, 1, 0, 1 },
- { 1, 1, 1, 1 },
+ {0, 0, 0, 0}, {1, 0, 1, 0}, {0, 1, 0, 1}, {1, 1, 1, 1},
};
const GLsizei kVertexStride = sizeof(Vertex);
@@ -82,15 +79,13 @@ public:
* Binds an attrib to the specified float vertex pointer.
* Assumes a stride of gTextureVertexStride and a size of 2.
*/
- void bindPositionVertexPointer(const GLvoid* vertices,
- GLsizei stride = kTextureVertexStride);
+ void bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
/**
* Binds an attrib to the specified float vertex pointer.
* Assumes a stride of gTextureVertexStride and a size of 2.
*/
- void bindTexCoordsVertexPointer(const GLvoid* vertices,
- GLsizei stride = kTextureVertexStride);
+ void bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
/**
* Resets the vertex pointers.
@@ -111,6 +106,7 @@ public:
///////////////////////////////////////////////////////////////////////////////
GLuint getUnitQuadVBO() { return mUnitQuadBuffer; }
GLuint getQuadListIBO() { return mQuadListIndices; }
+
private:
MeshState();
@@ -134,4 +130,4 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-#endif // RENDERSTATE_MESHSTATE_H
+#endif // RENDERSTATE_MESHSTATE_H
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index ea292d678c67..a0f5cb9d4e09 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -33,8 +33,8 @@ namespace uirenderer {
// OffscreenBuffer
////////////////////////////////////////////////////////////////////////////////
-OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches,
- uint32_t viewportWidth, uint32_t viewportHeight, bool wideColorGamut)
+OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t viewportWidth,
+ uint32_t viewportHeight, bool wideColorGamut)
: GpuMemoryTracker(GpuObjectType::OffscreenBuffer)
, renderState(renderState)
, viewportWidth(viewportWidth)
@@ -45,8 +45,8 @@ OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches,
uint32_t height = computeIdealDimension(viewportHeight);
ATRACE_FORMAT("Allocate %ux%u HW Layer", width, height);
caches.textureState().activateTexture(0);
- texture.resize(width, height,
- wideColorGamut ? GL_RGBA16F : caches.rgbaInternalFormat(), GL_RGBA);
+ texture.resize(width, height, wideColorGamut ? GL_RGBA16F : caches.rgbaInternalFormat(),
+ GL_RGBA);
texture.blend = true;
texture.setWrap(GL_CLAMP_TO_EDGE);
// not setting filter on texture, since it's set when drawing, based on transform
@@ -61,8 +61,8 @@ Rect OffscreenBuffer::getTextureCoordinates() {
void OffscreenBuffer::dirty(Rect dirtyArea) {
dirtyArea.doIntersect(0, 0, viewportWidth, viewportHeight);
if (!dirtyArea.isEmpty()) {
- region.orSelf(android::Rect(dirtyArea.left, dirtyArea.top,
- dirtyArea.right, dirtyArea.bottom));
+ region.orSelf(
+ android::Rect(dirtyArea.left, dirtyArea.top, dirtyArea.right, dirtyArea.bottom));
}
}
@@ -78,7 +78,8 @@ void OffscreenBuffer::updateMeshFromRegion() {
const float texX = 1.0f / float(texture.width());
const float texY = 1.0f / float(texture.height());
- FatVector<TextureVertex, 64> meshVector(count * 4); // uses heap if more than 64 vertices needed
+ FatVector<TextureVertex, 64> meshVector(count *
+ 4); // uses heap if more than 64 vertices needed
TextureVertex* mesh = &meshVector[0];
for (size_t i = 0; i < count; i++) {
const android::Rect* r = &rects[i];
@@ -94,10 +95,9 @@ void OffscreenBuffer::updateMeshFromRegion() {
TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
}
elementCount = count * 6;
- renderState.meshState().genOrUpdateMeshBuffer(&vbo,
- sizeof(TextureVertex) * count * 4,
- &meshVector[0],
- GL_DYNAMIC_DRAW); // TODO: GL_STATIC_DRAW if savelayer
+ renderState.meshState().genOrUpdateMeshBuffer(
+ &vbo, sizeof(TextureVertex) * count * 4, &meshVector[0],
+ GL_DYNAMIC_DRAW); // TODO: GL_STATIC_DRAW if savelayer
}
uint32_t OffscreenBuffer::computeIdealDimension(uint32_t dimension) {
@@ -117,12 +117,11 @@ OffscreenBuffer::~OffscreenBuffer() {
///////////////////////////////////////////////////////////////////////////////
OffscreenBufferPool::OffscreenBufferPool()
- // 4 screen-sized RGBA_8888 textures
- : mMaxSize(DeviceInfo::multiplyByResolution(4 * 4)) {
-}
+ // 4 screen-sized RGBA_8888 textures
+ : mMaxSize(DeviceInfo::multiplyByResolution(4 * 4)) {}
OffscreenBufferPool::~OffscreenBufferPool() {
- clear(); // TODO: unique_ptr?
+ clear(); // TODO: unique_ptr?
}
int OffscreenBufferPool::Entry::compare(const Entry& lhs, const Entry& rhs) {
@@ -143,8 +142,8 @@ void OffscreenBufferPool::clear() {
mSize = 0;
}
-OffscreenBuffer* OffscreenBufferPool::get(RenderState& renderState,
- const uint32_t width, const uint32_t height, bool wideColorGamut) {
+OffscreenBuffer* OffscreenBufferPool::get(RenderState& renderState, const uint32_t width,
+ const uint32_t height, bool wideColorGamut) {
OffscreenBuffer* layer = nullptr;
Entry entry(width, height, wideColorGamut);
@@ -159,18 +158,18 @@ OffscreenBuffer* OffscreenBufferPool::get(RenderState& renderState,
layer->viewportHeight = height;
mSize -= layer->getSizeInBytes();
} else {
- layer = new OffscreenBuffer(renderState, Caches::getInstance(),
- width, height, wideColorGamut);
+ layer = new OffscreenBuffer(renderState, Caches::getInstance(), width, height,
+ wideColorGamut);
}
return layer;
}
-OffscreenBuffer* OffscreenBufferPool::resize(OffscreenBuffer* layer,
- const uint32_t width, const uint32_t height) {
+OffscreenBuffer* OffscreenBufferPool::resize(OffscreenBuffer* layer, const uint32_t width,
+ const uint32_t height) {
RenderState& renderState = layer->renderState;
- if (layer->texture.width() == OffscreenBuffer::computeIdealDimension(width)
- && layer->texture.height() == OffscreenBuffer::computeIdealDimension(height)) {
+ if (layer->texture.width() == OffscreenBuffer::computeIdealDimension(width) &&
+ layer->texture.height() == OffscreenBuffer::computeIdealDimension(height)) {
// resize in place
layer->viewportWidth = width;
layer->viewportHeight = height;
@@ -214,5 +213,5 @@ void OffscreenBufferPool::putOrDelete(OffscreenBuffer* layer) {
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h
index d9422c9edd69..08ae052da391 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.h
+++ b/libs/hwui/renderstate/OffscreenBufferPool.h
@@ -18,10 +18,10 @@
#define ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
#include <GpuMemoryTracker.h>
+#include <ui/Region.h>
#include "Caches.h"
#include "Texture.h"
#include "utils/Macros.h"
-#include <ui/Region.h>
#include <set>
@@ -42,8 +42,8 @@ class RenderState;
*/
class OffscreenBuffer : GpuMemoryTracker {
public:
- OffscreenBuffer(RenderState& renderState, Caches& caches,
- uint32_t viewportWidth, uint32_t viewportHeight, bool wideColorGamut = false);
+ OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t viewportWidth,
+ uint32_t viewportHeight, bool wideColorGamut = false);
~OffscreenBuffer();
Rect getTextureCoordinates();
@@ -91,11 +91,11 @@ public:
OffscreenBufferPool();
~OffscreenBufferPool();
- WARN_UNUSED_RESULT OffscreenBuffer* get(RenderState& renderState,
- const uint32_t width, const uint32_t height, bool wideColorGamut = false);
+ WARN_UNUSED_RESULT OffscreenBuffer* get(RenderState& renderState, const uint32_t width,
+ const uint32_t height, bool wideColorGamut = false);
- WARN_UNUSED_RESULT OffscreenBuffer* resize(OffscreenBuffer* layer,
- const uint32_t width, const uint32_t height);
+ WARN_UNUSED_RESULT OffscreenBuffer* resize(OffscreenBuffer* layer, const uint32_t width,
+ const uint32_t height);
void putOrDelete(OffscreenBuffer* layer);
@@ -120,6 +120,7 @@ public:
* Prints out the content of the pool.
*/
void dump();
+
private:
struct Entry {
Entry() {}
@@ -133,36 +134,29 @@ private:
: layer(layer)
, width(layer->texture.width())
, height(layer->texture.height())
- , wideColorGamut(layer->wideColorGamut) {
- }
+ , wideColorGamut(layer->wideColorGamut) {}
static int compare(const Entry& lhs, const Entry& rhs);
- bool operator==(const Entry& other) const {
- return compare(*this, other) == 0;
- }
+ bool operator==(const Entry& other) const { return compare(*this, other) == 0; }
- bool operator!=(const Entry& other) const {
- return compare(*this, other) != 0;
- }
+ bool operator!=(const Entry& other) const { return compare(*this, other) != 0; }
- bool operator<(const Entry& other) const {
- return Entry::compare(*this, other) < 0;
- }
+ bool operator<(const Entry& other) const { return Entry::compare(*this, other) < 0; }
OffscreenBuffer* layer = nullptr;
uint32_t width = 0;
uint32_t height = 0;
bool wideColorGamut = false;
- }; // struct Entry
+ }; // struct Entry
std::multiset<Entry> mPool;
uint32_t mSize = 0;
uint32_t mMaxSize;
-}; // class OffscreenBufferCache
+}; // class OffscreenBufferCache
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
+#endif // ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
diff --git a/libs/hwui/renderstate/PixelBufferState.cpp b/libs/hwui/renderstate/PixelBufferState.cpp
index c23af5216592..3a6efb833c47 100644
--- a/libs/hwui/renderstate/PixelBufferState.cpp
+++ b/libs/hwui/renderstate/PixelBufferState.cpp
@@ -18,9 +18,7 @@
namespace android {
namespace uirenderer {
-PixelBufferState::PixelBufferState()
- : mCurrentPixelBuffer(0) {
-}
+PixelBufferState::PixelBufferState() : mCurrentPixelBuffer(0) {}
bool PixelBufferState::bind(GLuint buffer) {
if (mCurrentPixelBuffer != buffer) {
@@ -42,4 +40,3 @@ bool PixelBufferState::unbind() {
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/renderstate/PixelBufferState.h b/libs/hwui/renderstate/PixelBufferState.h
index 8dab21db176c..f7ae6c575f6a 100644
--- a/libs/hwui/renderstate/PixelBufferState.h
+++ b/libs/hwui/renderstate/PixelBufferState.h
@@ -22,10 +22,11 @@ namespace android {
namespace uirenderer {
class PixelBufferState {
- friend class Caches; // TODO: move to RenderState
+ friend class Caches; // TODO: move to RenderState
public:
bool bind(GLuint buffer);
bool unbind();
+
private:
PixelBufferState();
GLuint mCurrentPixelBuffer;
@@ -34,4 +35,4 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-#endif // RENDERSTATE_PIXELBUFFERSTATE_H
+#endif // RENDERSTATE_PIXELBUFFERSTATE_H
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 5fc5cb275741..5e33353c3ac6 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "renderstate/RenderState.h"
+#include <GpuMemoryTracker.h>
#include "DeferredLayerUpdater.h"
#include "GlLayer.h"
#include "VkLayer.h"
-#include <GpuMemoryTracker.h>
-#include "renderstate/RenderState.h"
#include "renderthread/CanvasContext.h"
#include "renderthread/EglManager.h"
@@ -31,21 +31,18 @@ namespace android {
namespace uirenderer {
RenderState::RenderState(renderthread::RenderThread& thread)
- : mRenderThread(thread)
- , mViewportWidth(0)
- , mViewportHeight(0)
- , mFramebuffer(0) {
+ : mRenderThread(thread), mViewportWidth(0), mViewportHeight(0), mFramebuffer(0) {
mThreadId = pthread_self();
}
RenderState::~RenderState() {
LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
- "State object lifecycle not managed correctly");
+ "State object lifecycle not managed correctly");
}
void RenderState::onGLContextCreated() {
LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
- "State object lifecycle not managed correctly");
+ "State object lifecycle not managed correctly");
GpuMemoryTracker::onGpuContextCreated();
mBlend = new Blend();
@@ -67,7 +64,7 @@ void RenderState::onGLContextCreated() {
static void layerLostGlContext(Layer* layer) {
LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL,
- "layerLostGlContext on non GL layer");
+ "layerLostGlContext on non GL layer");
static_cast<GlLayer*>(layer)->onGlContextLost();
}
@@ -94,7 +91,7 @@ void RenderState::onGLContextDestroyed() {
void RenderState::onVkContextCreated() {
LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
- "State object lifecycle not managed correctly");
+ "State object lifecycle not managed correctly");
GpuMemoryTracker::onGpuContextCreated();
}
@@ -105,8 +102,8 @@ static void layerDestroyedVkContext(Layer* layer) {
}
void RenderState::onVkContextDestroyed() {
- mLayerPool->clear();
std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerDestroyedVkContext);
+ destroyLayersInUpdater();
GpuMemoryTracker::onGpuContextDestroyed();
}
@@ -117,9 +114,9 @@ GrContext* RenderState::getGrContext() const {
void RenderState::flush(Caches::FlushMode mode) {
switch (mode) {
case Caches::FlushMode::Full:
- // fall through
+ // fall through
case Caches::FlushMode::Moderate:
- // fall through
+ // fall through
case Caches::FlushMode::Layers:
if (mLayerPool) mLayerPool->clear();
break;
@@ -140,7 +137,6 @@ void RenderState::setViewport(GLsizei width, GLsizei height) {
glViewport(0, 0, mViewportWidth, mViewportHeight);
}
-
void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) {
*outWidth = mViewportWidth;
*outHeight = mViewportHeight;
@@ -189,15 +185,13 @@ void RenderState::interruptForFunctorInvoke() {
meshState().disableTexCoordsVertexArray();
debugOverdraw(false, false);
// TODO: We need a way to know whether the functor is sRGB aware (b/32072673)
- if (mCaches->extensions().hasLinearBlending() &&
- mCaches->extensions().hasSRGBWriteControl()) {
+ if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
glDisable(GL_FRAMEBUFFER_SRGB_EXT);
}
}
void RenderState::resumeFromFunctorInvoke() {
- if (mCaches->extensions().hasLinearBlending() &&
- mCaches->extensions().hasSRGBWriteControl()) {
+ if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
glEnable(GL_FRAMEBUFFER_SRGB_EXT);
}
@@ -236,25 +230,11 @@ void RenderState::destroyLayersInUpdater() {
std::for_each(mActiveLayerUpdaters.begin(), mActiveLayerUpdaters.end(), destroyLayerInUpdater);
}
-class DecStrongTask : public renderthread::RenderTask {
-public:
- explicit DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}
-
- virtual void run() override {
- mObject->decStrong(nullptr);
- mObject = nullptr;
- delete this;
- }
-
-private:
- VirtualLightRefBase* mObject;
-};
-
void RenderState::postDecStrong(VirtualLightRefBase* object) {
if (pthread_equal(mThreadId, pthread_self())) {
object->decStrong(nullptr);
} else {
- mRenderThread.queue(new DecStrongTask(object));
+ mRenderThread.queue().post([object]() { object->decStrong(nullptr); });
}
}
@@ -263,7 +243,7 @@ void RenderState::postDecStrong(VirtualLightRefBase* object) {
///////////////////////////////////////////////////////////////////////////////
void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
- bool overrideDisableBlending) {
+ bool overrideDisableBlending) {
const Glop::Mesh& mesh = glop.mesh;
const Glop::Mesh::Vertices& vertices = mesh.vertices;
const Glop::Mesh::Indices& indices = mesh.indices;
@@ -280,21 +260,19 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
fill.program->setColor(fill.color);
}
- fill.program->set(orthoMatrix,
- glop.transform.modelView,
- glop.transform.meshTransform(),
- glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
+ fill.program->set(orthoMatrix, glop.transform.modelView, glop.transform.meshTransform(),
+ glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
// Color filter uniforms
if (fill.filterMode == ProgramDescription::ColorFilterMode::Blend) {
const FloatColor& color = fill.filter.color;
- glUniform4f(mCaches->program().getUniform("colorBlend"),
- color.r, color.g, color.b, color.a);
+ glUniform4f(mCaches->program().getUniform("colorBlend"), color.r, color.g, color.b,
+ color.a);
} else if (fill.filterMode == ProgramDescription::ColorFilterMode::Matrix) {
glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE,
- fill.filter.matrix.matrix);
+ fill.filter.matrix.matrix);
glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1,
- fill.filter.matrix.vector);
+ fill.filter.matrix.vector);
}
// Round rect clipping uniforms
@@ -309,15 +287,14 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
// Divide by the radius to simplify the calculations in the fragment shader
// roundRectPos is also passed from vertex shader relative to top/left & radius
glUniform4f(fill.program->getUniform("roundRectInnerRectLTWH"),
- innerRect.left / roundedOutRadius, innerRect.top / roundedOutRadius,
- (innerRect.right - innerRect.left) / roundedOutRadius,
- (innerRect.bottom - innerRect.top) / roundedOutRadius);
+ innerRect.left / roundedOutRadius, innerRect.top / roundedOutRadius,
+ (innerRect.right - innerRect.left) / roundedOutRadius,
+ (innerRect.bottom - innerRect.top) / roundedOutRadius);
- glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"),
- 1, GL_FALSE, &state->matrix.data[0]);
+ glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"), 1, GL_FALSE,
+ &state->matrix.data[0]);
- glUniform1f(fill.program->getUniform("roundRectRadius"),
- roundedOutRadius);
+ glUniform1f(fill.program->getUniform("roundRectRadius"), roundedOutRadius);
}
GL_CHECKPOINT(MODERATE);
@@ -347,8 +324,8 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
}
if (texture.textureTransform) {
- glUniformMatrix4fv(fill.program->getUniform("mainTextureTransform"), 1,
- GL_FALSE, &texture.textureTransform->data[0]);
+ glUniformMatrix4fv(fill.program->getUniform("mainTextureTransform"), 1, GL_FALSE,
+ &texture.textureTransform->data[0]);
}
}
@@ -363,12 +340,13 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
if (vertices.attribFlags & VertexAttribFlags::Color) {
colorLocation = fill.program->getAttrib("colors");
glEnableVertexAttribArray(colorLocation);
- glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, vertices.stride, vertices.color);
+ glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, vertices.stride,
+ vertices.color);
}
int alphaLocation = -1;
if (vertices.attribFlags & VertexAttribFlags::Alpha) {
// NOTE: alpha vertex position is computed assuming no VBO
- const void* alphaCoords = ((const GLbyte*) vertices.position) + kVertexAlphaOffset;
+ const void* alphaCoords = ((const GLbyte*)vertices.position) + kVertexAlphaOffset;
alphaLocation = fill.program->getAttrib("vtxAlpha");
glEnableVertexAttribArray(alphaLocation);
glVertexAttribPointer(alphaLocation, 1, GL_FLOAT, GL_FALSE, vertices.stride, alphaCoords);
@@ -377,8 +355,9 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
SkiaShader::apply(*mCaches, fill.skiaShaderData, mViewportWidth, mViewportHeight);
GL_CHECKPOINT(MODERATE);
- Texture* texture = (fill.skiaShaderData.skiaShaderType & kBitmap_SkiaShaderType) ?
- fill.skiaShaderData.bitmapData.bitmapTexture : nullptr;
+ Texture* texture = (fill.skiaShaderData.skiaShaderType & kBitmap_SkiaShaderType)
+ ? fill.skiaShaderData.bitmapData.bitmapTexture
+ : nullptr;
const AutoTexture autoCleanup(texture);
// If we have a shader and a base texture, the base texture is assumed to be an alpha mask
@@ -387,8 +366,8 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
if (colorSpaceTexture != nullptr) {
if (colorSpaceTexture->hasColorSpaceConversion()) {
const ColorSpaceConnector* connector = colorSpaceTexture->getColorSpaceConnector();
- glUniformMatrix3fv(fill.program->getUniform("colorSpaceMatrix"), 1,
- GL_FALSE, connector->getTransform().asArray());
+ glUniformMatrix3fv(fill.program->getUniform("colorSpaceMatrix"), 1, GL_FALSE,
+ connector->getTransform().asArray());
}
TransferFunctionType transferFunction = colorSpaceTexture->getTransferFunctionType();
@@ -401,15 +380,15 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
break;
case TransferFunctionType::Full:
glUniform1fv(fill.program->getUniform("transferFunction"), 7,
- reinterpret_cast<const float*>(&source.getTransferParameters().g));
+ reinterpret_cast<const float*>(&source.getTransferParameters().g));
break;
case TransferFunctionType::Limited:
glUniform1fv(fill.program->getUniform("transferFunction"), 5,
- reinterpret_cast<const float*>(&source.getTransferParameters().g));
+ reinterpret_cast<const float*>(&source.getTransferParameters().g));
break;
case TransferFunctionType::Gamma:
glUniform1f(fill.program->getUniform("transferFunctionGamma"),
- source.getTransferParameters().g);
+ source.getTransferParameters().g);
break;
}
}
@@ -435,16 +414,17 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
GLsizei elementsCount = mesh.elementCount;
const GLbyte* vertexData = static_cast<const GLbyte*>(vertices.position);
while (elementsCount > 0) {
- GLsizei drawCount = std::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
+ GLsizei drawCount = std::min(elementsCount, (GLsizei)kMaxNumberOfQuads * 6);
GLsizei vertexCount = (drawCount / 6) * 4;
meshState().bindPositionVertexPointer(vertexData, vertices.stride);
if (vertices.attribFlags & VertexAttribFlags::TextureCoord) {
- meshState().bindTexCoordsVertexPointer(
- vertexData + kMeshTextureOffset, vertices.stride);
+ meshState().bindTexCoordsVertexPointer(vertexData + kMeshTextureOffset,
+ vertices.stride);
}
if (mCaches->extensions().getMajorGlVersion() >= 3) {
- glDrawRangeElements(mesh.primitiveMode, 0, vertexCount-1, drawCount, GL_UNSIGNED_SHORT, nullptr);
+ glDrawRangeElements(mesh.primitiveMode, 0, vertexCount - 1, drawCount,
+ GL_UNSIGNED_SHORT, nullptr);
} else {
glDrawElements(mesh.primitiveMode, drawCount, GL_UNSIGNED_SHORT, nullptr);
}
@@ -453,10 +433,13 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
}
} else if (indices.bufferObject || indices.indices) {
if (mCaches->extensions().getMajorGlVersion() >= 3) {
- // use glDrawRangeElements to reduce CPU overhead (otherwise the driver has to determine the min/max index values)
- glDrawRangeElements(mesh.primitiveMode, 0, mesh.vertexCount-1, mesh.elementCount, GL_UNSIGNED_SHORT, indices.indices);
+ // use glDrawRangeElements to reduce CPU overhead (otherwise the driver has to determine
+ // the min/max index values)
+ glDrawRangeElements(mesh.primitiveMode, 0, mesh.vertexCount - 1, mesh.elementCount,
+ GL_UNSIGNED_SHORT, indices.indices);
} else {
- glDrawElements(mesh.primitiveMode, mesh.elementCount, GL_UNSIGNED_SHORT, indices.indices);
+ glDrawElements(mesh.primitiveMode, mesh.elementCount, GL_UNSIGNED_SHORT,
+ indices.indices);
}
} else {
glDrawArrays(mesh.primitiveMode, 0, mesh.elementCount);
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 315fa2db6878..e033cf2c5046 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -26,14 +26,14 @@
#include "renderstate/Stencil.h"
#include "utils/Macros.h"
-#include <set>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <private/hwui/DrawGlInfo.h>
#include <ui/Region.h>
-#include <utils/Mutex.h>
#include <utils/Functor.h>
+#include <utils/Mutex.h>
#include <utils/RefBase.h>
-#include <private/hwui/DrawGlInfo.h>
+#include <set>
class GrContext;
@@ -57,6 +57,7 @@ class RenderState {
friend class renderthread::RenderThread;
friend class Caches;
friend class renderthread::CacheManager;
+
public:
void onGLContextCreated();
void onGLContextDestroyed();
@@ -79,12 +80,8 @@ public:
void debugOverdraw(bool enable, bool clear);
- void registerLayer(Layer* layer) {
- mActiveLayers.insert(layer);
- }
- void unregisterLayer(Layer* layer) {
- mActiveLayers.erase(layer);
- }
+ void registerLayer(Layer* layer) { mActiveLayers.insert(layer); }
+ void unregisterLayer(Layer* layer) { mActiveLayers.erase(layer); }
void registerCanvasContext(renderthread::CanvasContext* context) {
mRegisteredContexts.insert(context);
@@ -127,7 +124,6 @@ private:
explicit RenderState(renderthread::RenderThread& thread);
~RenderState();
-
renderthread::RenderThread& mRenderThread;
Caches* mCaches = nullptr;
diff --git a/libs/hwui/renderstate/Scissor.cpp b/libs/hwui/renderstate/Scissor.cpp
index 61dd8c3200a4..e37ed029542b 100644
--- a/libs/hwui/renderstate/Scissor.cpp
+++ b/libs/hwui/renderstate/Scissor.cpp
@@ -23,12 +23,7 @@ namespace android {
namespace uirenderer {
Scissor::Scissor()
- : mEnabled(false)
- , mScissorX(0)
- , mScissorY(0)
- , mScissorWidth(0)
- , mScissorHeight(0) {
-}
+ : mEnabled(false), mScissorX(0), mScissorY(0), mScissorWidth(0), mScissorHeight(0) {}
bool Scissor::setEnabled(bool enabled) {
if (mEnabled != enabled) {
@@ -44,9 +39,8 @@ bool Scissor::setEnabled(bool enabled) {
}
bool Scissor::set(GLint x, GLint y, GLint width, GLint height) {
- if (mEnabled && (x != mScissorX || y != mScissorY
- || width != mScissorWidth || height != mScissorHeight)) {
-
+ if (mEnabled &&
+ (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight)) {
if (x < 0) {
width += x;
x = 0;
@@ -80,10 +74,7 @@ void Scissor::set(int viewportHeight, const Rect& clip) {
GLint width = std::max(0, ((int)clip.right) - x);
GLint height = std::max(0, (viewportHeight - (int)clip.top) - y);
- if (x != mScissorX
- || y != mScissorY
- || width != mScissorWidth
- || height != mScissorHeight) {
+ if (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight) {
glScissor(x, y, width, height);
mScissorX = x;
@@ -104,10 +95,9 @@ void Scissor::invalidate() {
}
void Scissor::dump() {
- ALOGD("Scissor: enabled %d, %d %d %d %d",
- mEnabled, mScissorX, mScissorY, mScissorWidth, mScissorHeight);
+ ALOGD("Scissor: enabled %d, %d %d %d %d", mEnabled, mScissorX, mScissorY, mScissorWidth,
+ mScissorHeight);
}
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/renderstate/Scissor.h b/libs/hwui/renderstate/Scissor.h
index f30224470059..2b04f4e1384a 100644
--- a/libs/hwui/renderstate/Scissor.h
+++ b/libs/hwui/renderstate/Scissor.h
@@ -26,6 +26,7 @@ class Rect;
class Scissor {
friend class RenderState;
+
public:
bool setEnabled(bool enabled);
bool set(GLint x, GLint y, GLint width, GLint height);
@@ -33,6 +34,7 @@ public:
void reset();
bool isEnabled() { return mEnabled; }
void dump();
+
private:
Scissor();
void invalidate();
@@ -46,4 +48,4 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-#endif // RENDERSTATE_SCISSOR_H
+#endif // RENDERSTATE_SCISSOR_H
diff --git a/libs/hwui/renderstate/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp
index f59442196af1..dc465fc7a6f8 100644
--- a/libs/hwui/renderstate/Stencil.cpp
+++ b/libs/hwui/renderstate/Stencil.cpp
@@ -136,5 +136,5 @@ void Stencil::dump() {
ALOGD("Stencil: state %d", mState);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/renderstate/Stencil.h b/libs/hwui/renderstate/Stencil.h
index 5f7d4056b51d..95f372344ee4 100644
--- a/libs/hwui/renderstate/Stencil.h
+++ b/libs/hwui/renderstate/Stencil.h
@@ -78,36 +78,26 @@ public:
/**
* Indicates whether either test or write is enabled.
*/
- bool isEnabled() {
- return mState != StencilState::Disabled;
- }
+ bool isEnabled() { return mState != StencilState::Disabled; }
/**
* Indicates whether testing only is enabled.
*/
- bool isTestEnabled() {
- return mState == StencilState::Test;
- }
+ bool isTestEnabled() { return mState == StencilState::Test; }
- bool isWriteEnabled() {
- return mState == StencilState::Write;
- }
+ bool isWriteEnabled() { return mState == StencilState::Write; }
void dump();
private:
- enum class StencilState {
- Disabled,
- Test,
- Write
- };
+ enum class StencilState { Disabled, Test, Write };
void enable();
StencilState mState = StencilState::Disabled;
-}; // class Stencil
+}; // class Stencil
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_STENCIL_H
+#endif // ANDROID_HWUI_STENCIL_H
diff --git a/libs/hwui/renderstate/TextureState.cpp b/libs/hwui/renderstate/TextureState.cpp
index f9a1f8c38895..470b4f5de97f 100644
--- a/libs/hwui/renderstate/TextureState.cpp
+++ b/libs/hwui/renderstate/TextureState.cpp
@@ -19,9 +19,9 @@
#include "utils/TraceUtils.h"
#include <GLES3/gl3.h>
-#include <memory>
-#include <SkCanvas.h>
#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <memory>
namespace android {
namespace uirenderer {
@@ -30,22 +30,16 @@ namespace uirenderer {
static const int SHADOW_LUT_SIZE = 128;
// Must define as many texture units as specified by kTextureUnitsCount
-const GLenum kTextureUnits[] = {
- GL_TEXTURE0,
- GL_TEXTURE1,
- GL_TEXTURE2,
- GL_TEXTURE3
-};
-
-TextureState::TextureState()
- : mTextureUnit(0) {
+const GLenum kTextureUnits[] = {GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_TEXTURE3};
+
+TextureState::TextureState() : mTextureUnit(0) {
glActiveTexture(kTextureUnits[0]);
resetBoundTextures();
GLint maxTextureUnits;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
LOG_ALWAYS_FATAL_IF(maxTextureUnits < kTextureUnitsCount,
- "At least %d texture units are required!", kTextureUnitsCount);
+ "At least %d texture units are required!", kTextureUnitsCount);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
@@ -86,8 +80,8 @@ void TextureState::constructTexture(Caches& caches) {
void TextureState::activateTexture(GLuint textureUnit) {
LOG_ALWAYS_FATAL_IF(textureUnit >= kTextureUnitsCount,
- "Tried to use texture unit index %d, only %d exist",
- textureUnit, kTextureUnitsCount);
+ "Tried to use texture unit index %d, only %d exist", textureUnit,
+ kTextureUnitsCount);
if (mTextureUnit != textureUnit) {
glActiveTexture(kTextureUnits[textureUnit]);
mTextureUnit = textureUnit;
@@ -151,4 +145,3 @@ void TextureState::unbindTexture(GLuint texture) {
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/renderstate/TextureState.h b/libs/hwui/renderstate/TextureState.h
index 7296fd39a705..f1996d431fa2 100644
--- a/libs/hwui/renderstate/TextureState.h
+++ b/libs/hwui/renderstate/TextureState.h
@@ -16,8 +16,8 @@
#ifndef RENDERSTATE_TEXTURESTATE_H
#define RENDERSTATE_TEXTURESTATE_H
-#include "Vertex.h"
#include "Texture.h"
+#include "Vertex.h"
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -29,9 +29,8 @@ namespace uirenderer {
class Texture;
class TextureState {
- friend class Caches; // TODO: move to RenderState
+ friend class Caches; // TODO: move to RenderState
public:
-
void constructTexture(Caches& caches);
/**
@@ -96,4 +95,4 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-#endif // RENDERSTATE_BLEND_H
+#endif // RENDERSTATE_BLEND_H
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 55694d046c2f..f510a2055309 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -17,11 +17,16 @@
#include "CacheManager.h"
#include "Layer.h"
+#include "Properties.h"
#include "RenderThread.h"
+#include "pipeline/skia/ShaderCache.h"
+#include "pipeline/skia/SkiaMemoryTracer.h"
#include "renderstate/RenderState.h"
-#include <gui/Surface.h>
#include <GrContextOptions.h>
+#include <SkExecutor.h>
+#include <SkGraphics.h>
+#include <gui/Surface.h>
#include <math.h>
#include <set>
@@ -41,19 +46,22 @@ namespace renderthread {
#define FONT_CACHE_MIN_MB (0.5f)
#define FONT_CACHE_MAX_MB (4.0f)
-CacheManager::CacheManager(const DisplayInfo& display)
- : mMaxSurfaceArea(display.w * display.h) {
- mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2,
- skiapipeline::VectorDrawableAtlas::StorageMode::allowSharedSurface);
+CacheManager::CacheManager(const DisplayInfo& display) : mMaxSurfaceArea(display.w * display.h) {
+ mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(
+ mMaxSurfaceArea / 2,
+ skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface);
+ if (Properties::isSkiaEnabled()) {
+ skiapipeline::ShaderCache::get().initShaderDiskCache();
+ }
}
-void CacheManager::reset(GrContext* context) {
- if (context != mGrContext.get()) {
+void CacheManager::reset(sk_sp<GrContext> context) {
+ if (context != mGrContext) {
destroy();
}
if (context) {
- mGrContext = sk_ref_sp(context);
+ mGrContext = std::move(context);
mGrContext->getResourceCacheLimits(&mMaxResources, nullptr);
updateContextCacheSizes();
}
@@ -62,7 +70,9 @@ void CacheManager::reset(GrContext* context) {
void CacheManager::destroy() {
// cleanup any caches here as the GrContext is about to go away...
mGrContext.reset(nullptr);
- mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2);
+ mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(
+ mMaxSurfaceArea / 2,
+ skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface);
}
void CacheManager::updateContextCacheSizes() {
@@ -72,6 +82,29 @@ void CacheManager::updateContextCacheSizes() {
mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes);
}
+class CacheManager::SkiaTaskProcessor : public TaskProcessor<bool>, public SkExecutor {
+public:
+ explicit SkiaTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
+
+ // This is really a Task<void> but that doesn't really work when Future<>
+ // expects to be able to get/set a value
+ struct SkiaTask : public Task<bool> {
+ std::function<void()> func;
+ };
+
+ virtual void add(std::function<void(void)> func) override {
+ sp<SkiaTask> task(new SkiaTask());
+ task->func = func;
+ TaskProcessor<bool>::add(task);
+ }
+
+ virtual void onProcess(const sp<Task<bool> >& task) override {
+ SkiaTask* t = static_cast<SkiaTask*>(task.get());
+ t->func();
+ task->setResult(true);
+ }
+};
+
void CacheManager::configureContext(GrContextOptions* contextOptions) {
contextOptions->fAllowPathMaskCaching = true;
@@ -94,6 +127,15 @@ void CacheManager::configureContext(GrContextOptions* contextOptions) {
// Skia's implementation doesn't provide a mechanism to resize the font cache due to
// the potential cost of recreating the glyphs.
contextOptions->fGlyphCacheTextureMaximumBytes = fontCacheMB * 1024 * 1024;
+
+ if (mTaskManager.canRunTasks()) {
+ if (!mTaskProcessor.get()) {
+ mTaskProcessor = new SkiaTaskProcessor(&mTaskManager);
+ }
+ contextOptions->fExecutor = mTaskProcessor.get();
+ }
+
+ contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get();
}
void CacheManager::trimMemory(TrimMemoryMode mode) {
@@ -105,11 +147,16 @@ void CacheManager::trimMemory(TrimMemoryMode mode) {
switch (mode) {
case TrimMemoryMode::Complete:
- mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2);
+ mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea / 2);
mGrContext->freeGpuResources();
break;
case TrimMemoryMode::UiHidden:
- mGrContext->purgeUnlockedResources(mMaxResourceBytes - mBackgroundResourceBytes, true);
+ // Here we purge all the unlocked scratch resources and then toggle the resources cache
+ // limits between the background and max amounts. This causes the unlocked resources
+ // that have persistent data to be purged in LRU order.
+ mGrContext->purgeUnlockedResources(true);
+ mGrContext->setResourceCacheLimits(mMaxResources, mBackgroundResourceBytes);
+ mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes);
break;
}
}
@@ -138,13 +185,30 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
return;
}
- size_t bytesCached;
- mGrContext->getResourceCacheUsage(nullptr, &bytesCached);
-
- log.appendFormat("Caches:\n");
+ log.appendFormat("Font Cache (CPU):\n");
+ log.appendFormat(" Size: %.2f kB \n", SkGraphics::GetFontCacheUsed() / 1024.0f);
+ log.appendFormat(" Glyph Count: %d \n", SkGraphics::GetFontCacheCountUsed());
+
+ log.appendFormat("CPU Caches:\n");
+ std::vector<skiapipeline::ResourcePair> cpuResourceMap = {
+ {"skia/sk_resource_cache/bitmap_", "Bitmaps"},
+ {"skia/sk_resource_cache/rrect-blur_", "Masks"},
+ {"skia/sk_resource_cache/rects-blur_", "Masks"},
+ {"skia/sk_resource_cache/tessellated", "Shadows"},
+ };
+ skiapipeline::SkiaMemoryTracer cpuTracer(cpuResourceMap, false);
+ SkGraphics::DumpMemoryStatistics(&cpuTracer);
+ cpuTracer.logOutput(log);
+
+ log.appendFormat("GPU Caches:\n");
+ skiapipeline::SkiaMemoryTracer gpuTracer("category", true);
+ mGrContext->dumpMemoryStatistics(&gpuTracer);
+ gpuTracer.logOutput(log);
+
+ log.appendFormat("Other Caches:\n");
log.appendFormat(" Current / Maximum\n");
- log.appendFormat(" VectorDrawableAtlas %6.2f kB / %6.2f kB (entries = %zu)\n",
- 0.0f, 0.0f, (size_t)0);
+ log.appendFormat(" VectorDrawableAtlas %6.2f kB / %6.2f KB (entries = %zu)\n", 0.0f, 0.0f,
+ (size_t)0);
if (renderState) {
if (renderState->mActiveLayers.size() > 0) {
@@ -153,24 +217,19 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
size_t layerMemoryTotal = 0;
for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
- it != renderState->mActiveLayers.end(); it++) {
+ it != renderState->mActiveLayers.end(); it++) {
const Layer* layer = *it;
const char* layerType = layer->getApi() == Layer::Api::OpenGL ? "GlLayer" : "VkLayer";
- log.appendFormat(" %s size %dx%d\n", layerType,
- layer->getWidth(), layer->getHeight());
+ log.appendFormat(" %s size %dx%d\n", layerType, layer->getWidth(),
+ layer->getHeight());
layerMemoryTotal += layer->getWidth() * layer->getHeight() * 4;
}
- log.appendFormat(" Layers Total %6.2f kB (numLayers = %zu)\n",
+ log.appendFormat(" Layers Total %6.2f KB (numLayers = %zu)\n",
layerMemoryTotal / 1024.0f, renderState->mActiveLayers.size());
}
-
- log.appendFormat("Total memory usage:\n");
- log.appendFormat(" %zu bytes, %.2f MB (%.2f MB is purgeable)\n",
- bytesCached, bytesCached / 1024.0f / 1024.0f,
- mGrContext->getResourceCachePurgeableBytes() / 1024.0f / 1024.0f);
-
-
+ log.appendFormat("Total GPU memory usage:\n");
+ gpuTracer.logTotals(log);
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 90362f33358d..7d733525194f 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -22,7 +22,10 @@
#include <ui/DisplayInfo.h>
#include <utils/String8.h>
#include <vector>
+
#include "pipeline/skia/VectorDrawableAtlas.h"
+#include "thread/TaskManager.h"
+#include "thread/TaskProcessor.h"
namespace android {
@@ -39,10 +42,7 @@ class RenderThread;
class CacheManager {
public:
- enum class TrimMemoryMode {
- Complete,
- UiHidden
- };
+ enum class TrimMemoryMode { Complete, UiHidden };
void configureContext(GrContextOptions* context);
void trimMemory(TrimMemoryMode mode);
@@ -54,13 +54,14 @@ public:
size_t getCacheSize() const { return mMaxResourceBytes; }
size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; }
+ TaskManager* getTaskManager() { return &mTaskManager; }
+
private:
friend class RenderThread;
CacheManager(const DisplayInfo& display);
-
- void reset(GrContext* grContext);
+ void reset(sk_sp<GrContext> grContext);
void destroy();
void updateContextCacheSizes();
@@ -77,6 +78,10 @@ private:
};
sp<skiapipeline::VectorDrawableAtlas> mVectorDrawableAtlas;
+
+ class SkiaTaskProcessor;
+ sp<SkiaTaskProcessor> mTaskProcessor;
+ TaskManager mTaskManager;
};
} /* namespace renderthread */
@@ -84,4 +89,3 @@ private:
} /* namespace android */
#endif /* CACHEMANAGER_H */
-
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b8815b56ecee..bfa2ae7e72ff 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -14,37 +14,39 @@
* limitations under the License.
*/
-#include <GpuMemoryTracker.h>
#include "CanvasContext.h"
+#include <GpuMemoryTracker.h>
#include "AnimationContext.h"
#include "Caches.h"
#include "EglManager.h"
#include "Frame.h"
#include "LayerUpdateQueue.h"
+#include "OpenGLPipeline.h"
#include "Properties.h"
#include "RenderThread.h"
#include "hwui/Canvas.h"
-#include "renderstate/RenderState.h"
-#include "renderstate/Stencil.h"
-#include "protos/hwui.pb.h"
-#include "OpenGLPipeline.h"
#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "pipeline/skia/SkiaPipeline.h"
#include "pipeline/skia/SkiaVulkanPipeline.h"
+#include "protos/hwui.pb.h"
+#include "renderstate/RenderState.h"
+#include "renderstate/Stencil.h"
#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
+#include "../Properties.h"
#include <cutils/properties.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <private/hwui/DrawGlInfo.h>
#include <strings.h>
-#include <algorithm>
#include <fcntl.h>
#include <sys/stat.h>
+#include <algorithm>
#include <cstdlib>
+#include <functional>
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
@@ -63,23 +65,22 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-CanvasContext* CanvasContext::create(RenderThread& thread,
- bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) {
-
+CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
+ RenderNode* rootRenderNode, IContextFactory* contextFactory) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
case RenderPipelineType::OpenGL:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<OpenGLPipeline>(thread));
+ std::make_unique<OpenGLPipeline>(thread));
case RenderPipelineType::SkiaGL:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
+ std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
case RenderPipelineType::SkiaVulkan:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
+ std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
return nullptr;
@@ -96,7 +97,7 @@ void CanvasContext::destroyLayer(RenderNode* node) {
skiapipeline::SkiaPipeline::destroyLayer(node);
break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -115,7 +116,7 @@ void CanvasContext::invokeFunctor(const RenderThread& thread, Functor* functor)
skiapipeline::SkiaVulkanPipeline::invokeFunctor(thread, functor);
break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -131,15 +132,16 @@ void CanvasContext::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
skiapipeline::SkiaPipeline::prepareToDraw(thread, bitmap);
break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
-CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory,
- std::unique_ptr<IRenderPipeline> renderPipeline)
+CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory,
+ std::unique_ptr<IRenderPipeline> renderPipeline)
: mRenderThread(thread)
+ , mGenerationID(0)
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
, mJankTracker(&thread.globalProfileData(), thread.mainDisplayInfo())
@@ -170,7 +172,7 @@ void CanvasContext::addRenderNode(RenderNode* node, bool placeFront) {
void CanvasContext::removeRenderNode(RenderNode* node) {
node->clearRoot();
mRenderNodes.erase(std::remove(mRenderNodes.begin(), mRenderNodes.end(), node),
- mRenderNodes.end());
+ mRenderNodes.end());
}
void CanvasContext::destroy() {
@@ -181,21 +183,22 @@ void CanvasContext::destroy() {
mAnimationContext->destroy();
}
-void CanvasContext::setSurface(Surface* surface) {
+void CanvasContext::setSurface(sp<Surface>&& surface) {
ATRACE_CALL();
- mNativeSurface = surface;
+ mNativeSurface = std::move(surface);
ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::Srgb;
- bool hasSurface = mRenderPipeline->setSurface(surface, mSwapBehavior, colorMode);
+ bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
mFrameNumber = -1;
if (hasSurface) {
- mHaveNewSurface = true;
- mSwapHistory.clear();
+ mHaveNewSurface = true;
+ mSwapHistory.clear();
} else {
- mRenderThread.removeFrameCallback(this);
+ mRenderThread.removeFrameCallback(this);
+ mGenerationID++;
}
}
@@ -203,15 +206,8 @@ void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
mSwapBehavior = swapBehavior;
}
-void CanvasContext::initialize(Surface* surface) {
- setSurface(surface);
-}
-
-void CanvasContext::updateSurface(Surface* surface) {
- setSurface(surface);
-}
-
-bool CanvasContext::pauseSurface(Surface* surface) {
+bool CanvasContext::pauseSurface() {
+ mGenerationID++;
return mRenderThread.removeFrameCallback(this);
}
@@ -219,6 +215,7 @@ void CanvasContext::setStopped(bool stopped) {
if (mStopped != stopped) {
mStopped = stopped;
if (mStopped) {
+ mGenerationID++;
mRenderThread.removeFrameCallback(this);
mRenderPipeline->onStop();
} else if (mIsDirty && hasSurface()) {
@@ -227,8 +224,7 @@ void CanvasContext::setStopped(bool stopped) {
}
}
-void CanvasContext::setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+void CanvasContext::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
mLightGeometry.radius = lightRadius;
mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
mLightInfo.spotShadowAlpha = spotShadowAlpha;
@@ -262,7 +258,7 @@ bool CanvasContext::makeCurrent() {
return true;
default:
LOG_ALWAYS_FATAL("unexpected result %d from IRenderPipeline::makeCurrent",
- (int32_t) result);
+ (int32_t)result);
}
return true;
@@ -285,8 +281,7 @@ bool CanvasContext::isSwapChainStuffed() {
// Was there a happy queue & dequeue time? If so, don't
// consider it stuffed
- if (swapA.dequeueDuration < SLOW_THRESHOLD
- && swapA.queueDuration < SLOW_THRESHOLD) {
+ if (swapA.dequeueDuration < SLOW_THRESHOLD && swapA.queueDuration < SLOW_THRESHOLD) {
return false;
}
@@ -301,8 +296,7 @@ bool CanvasContext::isSwapChainStuffed() {
// Was there a happy queue & dequeue time? If so, don't
// consider it stuffed
- if (swapB.dequeueDuration < SLOW_THRESHOLD
- && swapB.queueDuration < SLOW_THRESHOLD) {
+ if (swapB.dequeueDuration < SLOW_THRESHOLD && swapB.queueDuration < SLOW_THRESHOLD) {
return false;
}
@@ -314,8 +308,8 @@ bool CanvasContext::isSwapChainStuffed() {
return true;
}
-void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
- int64_t syncQueued, RenderNode* target) {
+void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued,
+ RenderNode* target) {
mRenderThread.removeFrameCallback(this);
// If the previous frame was dropped we don't need to hold onto it, so
@@ -331,6 +325,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
info.layerUpdateQueue = &mLayerUpdateQueue;
mAnimationContext->startFrame(info.mode);
+ mRenderPipeline->onPrepareTree();
for (const sp<RenderNode>& node : mRenderNodes) {
// Only the primary target node will be drawn full - all other nodes would get drawn in
// real time mode. In case of a window, the primary node is the window content and the other
@@ -365,8 +360,15 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
// Already drew for this vsync pulse, UI draw request missed
// the deadline for RT animations
info.out.canDrawThisFrame = false;
- } else if (vsyncDelta >= mRenderThread.timeLord().frameIntervalNanos() * 3
- || (latestVsync - mLastDropVsync) < 500_ms) {
+ }
+ /* This logic exists to try and recover from a display latch miss, which essentially
+ * results in the bufferqueue being double-buffered instead of triple-buffered.
+ * SurfaceFlinger itself now tries to handle & recover from this situation, so this
+ * logic should no longer be necessary. As it's occasionally triggering when
+ * undesired disable it.
+ * TODO: Remove this entirely if the results are solid.
+ else if (vsyncDelta >= mRenderThread.timeLord().frameIntervalNanos() * 3 ||
+ (latestVsync - mLastDropVsync) < 500_ms) {
// It's been several frame intervals, assume the buffer queue is fine
// or the last drop was too recent
info.out.canDrawThisFrame = true;
@@ -377,19 +379,48 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
mLastDropVsync = mRenderThread.timeLord().latestVsync();
}
}
+ */
} else {
info.out.canDrawThisFrame = true;
}
+ // TODO: Do we need to abort out if the backdrop is added but not ready? Should that even
+ // be an allowable combination?
+ if (mRenderNodes.size() > 2 && !mRenderNodes[1]->isRenderable()) {
+ info.out.canDrawThisFrame = false;
+ }
+
if (!info.out.canDrawThisFrame) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
}
+ bool postedFrameCallback = false;
if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
+ if (CC_UNLIKELY(!Properties::enableRTAnimations)) {
+ info.out.requiresUiRedraw = true;
+ }
if (!info.out.requiresUiRedraw) {
// If animationsNeedsRedraw is set don't bother posting for an RT anim
// as we will just end up fighting the UI thread.
mRenderThread.postFrameCallback(this);
+ postedFrameCallback = true;
+ }
+ }
+
+ if (!postedFrameCallback &&
+ info.out.animatedImageDelay != TreeInfo::Out::kNoAnimatedImageDelay) {
+ // Subtract the time of one frame so it can be displayed on time.
+ const nsecs_t kFrameTime = mRenderThread.timeLord().frameIntervalNanos();
+ if (info.out.animatedImageDelay <= kFrameTime) {
+ mRenderThread.postFrameCallback(this);
+ } else {
+ const auto delay = info.out.animatedImageDelay - kFrameTime;
+ int genId = mGenerationID;
+ mRenderThread.queue().postDelayed(delay, [this, genId]() {
+ if (mGenerationID == genId) {
+ mRenderThread.postFrameCallback(this);
+ }
+ });
}
}
}
@@ -397,6 +428,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
void CanvasContext::stopDrawing() {
mRenderThread.removeFrameCallback(this);
mAnimationContext->pauseAnimators();
+ mGenerationID++;
}
void CanvasContext::notifyFramePending() {
@@ -409,10 +441,10 @@ void CanvasContext::draw() {
mDamageAccumulator.finish(&dirty);
// TODO: Re-enable after figuring out cause of b/22592975
-// if (dirty.isEmpty() && Properties::skipEmptyFrames) {
-// mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
-// return;
-// }
+ // if (dirty.isEmpty() && Properties::skipEmptyFrames) {
+ // mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+ // return;
+ // }
mCurrentFrameInfo->markIssueDrawCommandsStart();
@@ -421,18 +453,21 @@ void CanvasContext::draw() {
SkRect windowDirty = computeDirtyRect(frame, &dirty);
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
- mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo, mRenderNodes, &(profiler()));
+ mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo,
+ mRenderNodes, &(profiler()));
+
+ int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
waitOnFences();
bool requireSwap = false;
- bool didSwap = mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo,
- &requireSwap);
+ bool didSwap =
+ mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
mIsDirty = false;
if (requireSwap) {
- if (!didSwap) { //some error happened
+ if (!didSwap) { // some error happened
setSurface(nullptr);
}
SwapHistory& swap = mSwapHistory.next();
@@ -456,10 +491,8 @@ void CanvasContext::draw() {
swap.dequeueDuration = 0;
swap.queueDuration = 0;
}
- mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration)
- = swap.dequeueDuration;
- mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration)
- = swap.queueDuration;
+ mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = swap.dequeueDuration;
+ mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = swap.queueDuration;
mHaveNewSurface = false;
mFrameNumber = -1;
} else {
@@ -471,9 +504,9 @@ void CanvasContext::draw() {
mCurrentFrameInfo->markFrameCompleted();
#if LOG_FRAMETIME_MMA
- float thisFrame = mCurrentFrameInfo->duration(
- FrameInfoIndex::IssueDrawCommandsStart,
- FrameInfoIndex::FrameCompleted) / NANOS_PER_MILLIS_F;
+ float thisFrame = mCurrentFrameInfo->duration(FrameInfoIndex::IssueDrawCommandsStart,
+ FrameInfoIndex::FrameCompleted) /
+ NANOS_PER_MILLIS_F;
if (sFrameCount) {
sBenchMma = ((9 * sBenchMma) + thisFrame) / 10;
} else {
@@ -485,6 +518,13 @@ void CanvasContext::draw() {
}
#endif
+ if (didSwap) {
+ for (auto& func : mFrameCompleteCallbacks) {
+ std::invoke(func, frameCompleteNr);
+ }
+ mFrameCompleteCallbacks.clear();
+ }
+
mJankTracker.finishFrame(*mCurrentFrameInfo);
if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
@@ -498,7 +538,6 @@ void CanvasContext::draw() {
caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted();
}
#endif
-
}
// Called by choreographer to do an RT-driven animation
@@ -512,9 +551,7 @@ void CanvasContext::prepareAndDraw(RenderNode* node) {
nsecs_t vsync = mRenderThread.timeLord().computeFrameTimeNanos();
int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
- UiFrameInfoBuilder(frameInfo)
- .addFlag(FrameInfoFlags::RTAnimation)
- .setVsync(vsync, vsync);
+ UiFrameInfoBuilder(frameInfo).addFlag(FrameInfoFlags::RTAnimation).setVsync(vsync, vsync);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC), node);
@@ -536,7 +573,7 @@ void CanvasContext::freePrefetchedLayers() {
if (mPrefetchedLayers.size()) {
for (auto& node : mPrefetchedLayers) {
ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...",
- node->getName());
+ node->getName());
node->destroyLayers();
node->decStrong(nullptr);
}
@@ -562,8 +599,8 @@ void CanvasContext::buildLayer(RenderNode* node) {
// purposes when the frame is actually drawn
node->setPropertyFieldsDirty(RenderNode::GENERIC);
- mRenderPipeline->renderLayers(mLightGeometry, &mLayerUpdateQueue,
- mOpaque, mWideColorGamut, mLightInfo);
+ mRenderPipeline->renderLayers(mLightGeometry, &mLayerUpdateQueue, mOpaque, mWideColorGamut,
+ mLightInfo);
node->incStrong(nullptr);
mPrefetchedLayers.insert(node);
@@ -614,7 +651,7 @@ void CanvasContext::trimMemory(RenderThread& thread, int level) {
break;
}
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -641,7 +678,7 @@ void CanvasContext::serializeDisplayListTree() {
using namespace google::protobuf::io;
char package[128];
// Check whether tracing is enabled for this process.
- FILE * file = fopen("/proc/self/cmdline", "r");
+ FILE* file = fopen("/proc/self/cmdline", "r");
if (file) {
if (!fgets(package, 128, file)) {
ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno);
@@ -650,8 +687,7 @@ void CanvasContext::serializeDisplayListTree() {
}
fclose(file);
} else {
- ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno),
- errno);
+ ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno), errno);
return;
}
char path[1024];
@@ -682,8 +718,7 @@ void CanvasContext::waitOnFences() {
class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> {
public:
- explicit FuncTaskProcessor(TaskManager* taskManager)
- : TaskProcessor<bool>(taskManager) {}
+ explicit FuncTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
virtual void onProcess(const sp<Task<bool> >& task) override {
FuncTask* t = static_cast<FuncTask*>(task.get());
@@ -721,8 +756,8 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
dirty->setEmpty();
} else {
if (!dirty->isEmpty() && !dirty->intersect(0, 0, frame.width(), frame.height())) {
- ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?",
- SK_RECT_ARGS(*dirty), frame.width(), frame.height());
+ ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?", SK_RECT_ARGS(*dirty),
+ frame.width(), frame.height());
dirty->setEmpty();
}
profiler().unionDirty(dirty);
@@ -742,7 +777,7 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
// last frame so there's nothing to union() against
// Therefore we only care about the > 1 case.
if (frame.bufferAge() > 1) {
- if (frame.bufferAge() > (int) mSwapHistory.size()) {
+ if (frame.bufferAge() > (int)mSwapHistory.size()) {
// We don't have enough history to handle this old of a buffer
// Just do a full-draw
dirty->set(0, 0, frame.width(), frame.height());
@@ -751,7 +786,7 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
// to the damage history (happens below)
// So we need to damage
for (int i = mSwapHistory.size() - 1;
- i > ((int) mSwapHistory.size()) - frame.bufferAge(); i--) {
+ i > ((int)mSwapHistory.size()) - frame.bufferAge(); i--) {
dirty->join(mSwapHistory[i].damage);
}
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4a5b2c72b02a..1c4e02d7df70 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -27,17 +27,17 @@
#include "IRenderPipeline.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
-#include "thread/Task.h"
-#include "thread/TaskProcessor.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
+#include "thread/Task.h"
+#include "thread/TaskProcessor.h"
-#include <cutils/compiler.h>
#include <EGL/egl.h>
#include <SkBitmap.h>
#include <SkRect.h>
-#include <utils/Functor.h>
+#include <cutils/compiler.h>
#include <gui/Surface.h>
+#include <utils/Functor.h>
#include <functional>
#include <set>
@@ -49,6 +49,7 @@ namespace uirenderer {
class AnimationContext;
class DeferredLayerUpdater;
+class ErrorHandler;
class Layer;
class Rect;
class RenderState;
@@ -63,8 +64,8 @@ class Frame;
// TODO: Rename to Renderer or some other per-window, top-level manager
class CanvasContext : public IFrameCallback {
public:
- static CanvasContext* create(RenderThread& thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory);
+ static CanvasContext* create(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory);
virtual ~CanvasContext();
/**
@@ -74,8 +75,10 @@ public:
*
* @return true if the layer has been created or updated
*/
- bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& dmgAccumulator) {
- return mRenderPipeline->createOrUpdateLayer(node, dmgAccumulator, mWideColorGamut);
+ bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& dmgAccumulator,
+ ErrorHandler* errorHandler) {
+ return mRenderPipeline->createOrUpdateLayer(node, dmgAccumulator, mWideColorGamut,
+ errorHandler);
}
/**
@@ -89,9 +92,7 @@ public:
bool pinImages(std::vector<SkImage*>& mutableImages) {
return mRenderPipeline->pinImages(mutableImages);
}
- bool pinImages(LsaVector<sk_sp<Bitmap>>& images) {
- return mRenderPipeline->pinImages(images);
- }
+ bool pinImages(LsaVector<sk_sp<Bitmap>>& images) { return mRenderPipeline->pinImages(images); }
/**
* Unpin any image that had be previously pinned to the GPU cache
@@ -117,20 +118,17 @@ public:
// Won't take effect until next EGLSurface creation
void setSwapBehavior(SwapBehavior swapBehavior);
- void initialize(Surface* surface);
- void updateSurface(Surface* surface);
- bool pauseSurface(Surface* surface);
+ void setSurface(sp<Surface>&& surface);
+ bool pauseSurface();
void setStopped(bool stopped);
bool hasSurface() { return mNativeSurface.get(); }
- void setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setLightCenter(const Vector3& lightCenter);
void setOpaque(bool opaque);
void setWideGamut(bool wideGamut);
bool makeCurrent();
- void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
- int64_t syncQueued, RenderNode* target);
+ void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
void draw();
void destroy();
@@ -162,13 +160,9 @@ public:
void addRenderNode(RenderNode* node, bool placeFront);
void removeRenderNode(RenderNode* node);
- void setContentDrawBounds(const Rect& bounds) {
- mContentDrawBounds = bounds;
- }
+ void setContentDrawBounds(const Rect& bounds) { mContentDrawBounds = bounds; }
- RenderState& getRenderState() {
- return mRenderThread.renderState();
- }
+ RenderState& getRenderState() { return mRenderThread.renderState(); }
void addFrameMetricsObserver(FrameMetricsObserver* observer) {
if (mFrameMetricsReporter.get() == nullptr) {
@@ -196,17 +190,19 @@ public:
IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); }
+ void addFrameCompleteListener(std::function<void(int64_t)>&& func) {
+ mFrameCompleteCallbacks.push_back(std::move(func));
+ }
+
private:
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
- IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
+ IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
// lifecycle tracking
friend class android::uirenderer::RenderState;
- void setSurface(Surface* window);
-
void freePrefetchedLayers();
bool isSwapChainStuffed();
@@ -221,6 +217,9 @@ private:
// stopped indicates the CanvasContext will reject actual redraw operations,
// and defer repaint until it is un-stopped
bool mStopped = false;
+ // Incremented each time the CanvasContext is stopped. Used to ignore
+ // delayed messages that are triggered after stopping.
+ int mGenerationID;
// CanvasContext is dirty if it has received an update that it has not
// painted onto its surface.
bool mIsDirty = false;
@@ -242,14 +241,14 @@ private:
bool mOpaque;
bool mWideColorGamut = false;
BakedOpRenderer::LightInfo mLightInfo;
- FrameBuilder::LightGeometry mLightGeometry = { {0, 0, 0}, 0 };
+ FrameBuilder::LightGeometry mLightGeometry = {{0, 0, 0}, 0};
bool mHaveNewSurface = false;
DamageAccumulator mDamageAccumulator;
LayerUpdateQueue mLayerUpdateQueue;
std::unique_ptr<AnimationContext> mAnimationContext;
- std::vector< sp<RenderNode> > mRenderNodes;
+ std::vector<sp<RenderNode>> mRenderNodes;
FrameInfo* mCurrentFrameInfo = nullptr;
std::string mName;
@@ -269,9 +268,11 @@ private:
};
class FuncTaskProcessor;
- std::vector< sp<FuncTask> > mFrameFences;
- sp<TaskProcessor<bool> > mFrameWorkProcessor;
+ std::vector<sp<FuncTask>> mFrameFences;
+ sp<TaskProcessor<bool>> mFrameWorkProcessor;
std::unique_ptr<IRenderPipeline> mRenderPipeline;
+
+ std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index a097272df359..51eeab7e46ce 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -33,21 +33,20 @@ DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
, mContentDrawBounds(0, 0, 0, 0)
- , mSyncResult(SyncResult::OK) {
-}
+ , mSyncResult(SyncResult::OK) {}
-DrawFrameTask::~DrawFrameTask() {
-}
+DrawFrameTask::~DrawFrameTask() {}
void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
- RenderNode* targetNode) {
+ RenderNode* targetNode) {
mRenderThread = thread;
mContext = context;
mTargetNode = targetNode;
}
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
- LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to pushLayerUpdate with!");
+ LOG_ALWAYS_FATAL_IF(!mContext,
+ "Lifecycle violation, there's no context to pushLayerUpdate with!");
for (size_t i = 0; i < mLayers.size(); i++) {
if (mLayers[i].get() == layer) {
@@ -78,7 +77,7 @@ int DrawFrameTask::drawFrame() {
void DrawFrameTask::postAndWait() {
AutoMutex _lock(mLock);
- mRenderThread->queue(this);
+ mRenderThread->queue().post([this]() { run(); });
mSignal.wait(mLock);
}
@@ -91,16 +90,30 @@ void DrawFrameTask::run() {
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
+
+ if (mFrameCompleteCallback) {
+ mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback));
+ mFrameCompleteCallback = nullptr;
+ }
}
// Grab a copy of everything we need
CanvasContext* context = mContext;
+ std::function<void(int64_t)> callback = std::move(mFrameCallback);
+ mFrameCallback = nullptr;
// From this point on anything in "this" is *UNSAFE TO ACCESS*
if (canUnblockUiThread) {
unblockUiThread();
}
+ // Even if we aren't drawing this vsync pulse the next frame number will still be accurate
+ if (CC_UNLIKELY(callback)) {
+ context->enqueueFrameWork([callback, frameNr = context->getFrameNumber()]() {
+ callback(frameNr);
+ });
+ }
+
if (CC_LIKELY(canDrawThisFrame)) {
context->draw();
} else {
@@ -144,6 +157,9 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
mSyncResult |= SyncResult::UIRedrawRequired;
}
}
+ if (!info.out.canDrawThisFrame) {
+ mSyncResult |= SyncResult::FrameDropped;
+ }
// If prepareTextures is false, we ran out of texture cache space
return info.prepareTextures;
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 83ecb98f548f..2c46762fee5c 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -24,8 +24,8 @@
#include "RenderTask.h"
-#include "../Rect.h"
#include "../FrameInfo.h"
+#include "../Rect.h"
#include "../TreeInfo.h"
namespace android {
@@ -46,6 +46,7 @@ enum {
UIRedrawRequired = 1 << 0,
LostSurfaceRewardIfFound = 1 << 1,
ContextIsStopped = 1 << 2,
+ FrameDropped = 1 << 3,
};
}
@@ -55,7 +56,7 @@ enum {
* tracked across many frames not just a single frame.
* It is the sync-state task, and will kick off the post-sync draw
*/
-class DrawFrameTask : public RenderTask {
+class DrawFrameTask {
public:
DrawFrameTask();
virtual ~DrawFrameTask();
@@ -72,7 +73,15 @@ public:
int64_t* frameInfo() { return mFrameInfo; }
- virtual void run() override;
+ void run();
+
+ void setFrameCallback(std::function<void(int64_t)>&& callback) {
+ mFrameCallback = std::move(callback);
+ }
+
+ void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+ mFrameCompleteCallback = std::move(callback);
+ }
private:
void postAndWait();
@@ -90,12 +99,15 @@ private:
/*********************************************
* Single frame data
*********************************************/
- std::vector< sp<DeferredLayerUpdater> > mLayers;
+ std::vector<sp<DeferredLayerUpdater> > mLayers;
int mSyncResult;
int64_t mSyncQueued;
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
+
+ std::function<void(int64_t)> mFrameCallback;
+ std::function<void(int64_t)> mFrameCompleteCallback;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index bd4708da562a..6e239e357cf6 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -18,17 +18,17 @@
#include <string>
-#include "utils/StringUtils.h"
#include <cutils/properties.h>
#include <log/log.h>
+#include "utils/StringUtils.h"
#include "Caches.h"
#include "DeviceInfo.h"
#include "Frame.h"
#include "Properties.h"
#include "RenderThread.h"
-#include "renderstate/RenderState.h"
#include "Texture.h"
+#include "renderstate/RenderState.h"
#include <EGL/eglext.h>
#include <GrContextOptions.h>
@@ -47,7 +47,9 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-#define ERROR_CASE(x) case x: return #x;
+#define ERROR_CASE(x) \
+ case x: \
+ return #x;
static const char* egl_error_str(EGLint error) {
switch (error) {
ERROR_CASE(EGL_SUCCESS)
@@ -65,8 +67,8 @@ static const char* egl_error_str(EGLint error) {
ERROR_CASE(EGL_BAD_PARAMETER)
ERROR_CASE(EGL_BAD_SURFACE)
ERROR_CASE(EGL_CONTEXT_LOST)
- default:
- return "Unknown error";
+ default:
+ return "Unknown error";
}
}
const char* EglManager::eglErrorString() {
@@ -80,6 +82,7 @@ static struct {
bool pixelFormatFloat = false;
bool glColorSpace = false;
bool scRGB = false;
+ bool contextPriority = false;
} EglExtensions;
EglManager::EglManager(RenderThread& thread)
@@ -89,8 +92,7 @@ EglManager::EglManager(RenderThread& thread)
, mEglConfigWideGamut(nullptr)
, mEglContext(EGL_NO_CONTEXT)
, mPBufferSurface(EGL_NO_SURFACE)
- , mCurrentSurface(EGL_NO_SURFACE) {
-}
+ , mCurrentSurface(EGL_NO_SURFACE) {}
void EglManager::initialize() {
if (hasEglContext()) return;
@@ -98,12 +100,12 @@ void EglManager::initialize() {
ATRACE_NAME("Creating EGLContext");
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
- "Failed to get EGL_DEFAULT_DISPLAY! err=%s", eglErrorString());
+ LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+ eglErrorString());
EGLint major, minor;
LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
- "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());
+ "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());
ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
@@ -138,26 +140,26 @@ void EglManager::initialize() {
LOG_ALWAYS_FATAL_IF(!glInterface.get());
GrContextOptions options;
- options.fGpuPathRenderers &= ~GrContextOptions::GpuPathRenderers::kDistanceField;
+ options.fDisableDistanceFieldPaths = true;
mRenderThread.cacheManager().configureContext(&options);
- mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend,
- (GrBackendContext)glInterface.get(), options));
+ sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
+ LOG_ALWAYS_FATAL_IF(!grContext.get());
+ mRenderThread.setGrContext(grContext);
}
}
void EglManager::initExtensions() {
- auto extensions = StringUtils::split(
- eglQueryString(mEglDisplay, EGL_EXTENSIONS));
+ auto extensions = StringUtils::split(eglQueryString(mEglDisplay, EGL_EXTENSIONS));
// For our purposes we don't care if EGL_BUFFER_AGE is a result of
// EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered
// under EGL_KHR_partial_update and we don't need the expanded scope
// that EGL_EXT_buffer_age provides.
- EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age")
- || extensions.has("EGL_KHR_partial_update");
+ EglExtensions.bufferAge =
+ extensions.has("EGL_EXT_buffer_age") || extensions.has("EGL_KHR_partial_update");
EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update");
LOG_ALWAYS_FATAL_IF(!extensions.has("EGL_KHR_swap_buffers_with_damage"),
- "Missing required extension EGL_KHR_swap_buffers_with_damage");
+ "Missing required extension EGL_KHR_swap_buffers_with_damage");
EglExtensions.glColorSpace = extensions.has("EGL_KHR_gl_colorspace");
EglExtensions.noConfigContext = extensions.has("EGL_KHR_no_config_context");
@@ -167,6 +169,7 @@ void EglManager::initExtensions() {
#else
EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb");
#endif
+ EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
}
bool EglManager::hasEglContext() {
@@ -175,30 +178,37 @@ bool EglManager::hasEglContext() {
void EglManager::loadConfigs() {
ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
- EGLint swapBehavior = (mSwapBehavior == SwapBehavior::Preserved)
- ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
- EGLint attribs[] = {
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 0,
- EGL_CONFIG_CAVEAT, EGL_NONE,
- EGL_STENCIL_SIZE, Stencil::getStencilSize(),
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE
- };
+ EGLint swapBehavior =
+ (mSwapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+ EGLint attribs[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_CONFIG_CAVEAT,
+ EGL_NONE,
+ EGL_STENCIL_SIZE,
+ Stencil::getStencilSize(),
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | swapBehavior,
+ EGL_NONE};
EGLint numConfigs = 1;
- if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, numConfigs, &numConfigs)
- || numConfigs != 1) {
+ if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, numConfigs, &numConfigs) ||
+ numConfigs != 1) {
if (mSwapBehavior == SwapBehavior::Preserved) {
// Try again without dirty regions enabled
ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
mSwapBehavior = SwapBehavior::Discard;
loadConfigs();
- return; // the call to loadConfigs() we just made picks the wide gamut config
+ return; // the call to loadConfigs() we just made picks the wide gamut config
} else {
// Failed to get a valid config
LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
@@ -207,22 +217,30 @@ void EglManager::loadConfigs() {
if (EglExtensions.pixelFormatFloat) {
// If we reached this point, we have a valid swap behavior
- EGLint attribs16F[] = {
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
- EGL_RED_SIZE, 16,
- EGL_GREEN_SIZE, 16,
- EGL_BLUE_SIZE, 16,
- EGL_ALPHA_SIZE, 16,
- EGL_DEPTH_SIZE, 0,
- EGL_STENCIL_SIZE, Stencil::getStencilSize(),
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE
- };
+ EGLint attribs16F[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_COLOR_COMPONENT_TYPE_EXT,
+ EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ EGL_RED_SIZE,
+ 16,
+ EGL_GREEN_SIZE,
+ 16,
+ EGL_BLUE_SIZE,
+ 16,
+ EGL_ALPHA_SIZE,
+ 16,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_STENCIL_SIZE,
+ Stencil::getStencilSize(),
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | swapBehavior,
+ EGL_NONE};
numConfigs = 1;
- if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs, &numConfigs)
- || numConfigs != 1) {
+ if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs,
+ &numConfigs) ||
+ numConfigs != 1) {
ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
eglErrorString());
EglExtensions.pixelFormatFloat = false;
@@ -231,23 +249,28 @@ void EglManager::loadConfigs() {
}
void EglManager::createContext() {
- EGLint attribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION,
- EGL_NONE
- };
- mEglContext = eglCreateContext(mEglDisplay,
- EglExtensions.noConfigContext ? ((EGLConfig) nullptr) : mEglConfig,
- EGL_NO_CONTEXT, attribs);
- LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
- "Failed to create context, error = %s", eglErrorString());
+ std::vector<EGLint> contextAttributes;
+ contextAttributes.reserve(5);
+ contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttributes.push_back(GLES_VERSION);
+ if (Properties::contextPriority != 0 && EglExtensions.contextPriority) {
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
+ contextAttributes.push_back(Properties::contextPriority);
+ }
+ contextAttributes.push_back(EGL_NONE);
+ mEglContext = eglCreateContext(
+ mEglDisplay, EglExtensions.noConfigContext ? ((EGLConfig) nullptr) : mEglConfig,
+ EGL_NO_CONTEXT, contextAttributes.data());
+ LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, "Failed to create context, error = %s",
+ eglErrorString());
}
void EglManager::createPBufferSurface() {
LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
- "usePBufferSurface() called on uninitialized GlobalContext!");
+ "usePBufferSurface() called on uninitialized GlobalContext!");
if (mPBufferSurface == EGL_NO_SURFACE) {
- EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+ EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
}
}
@@ -255,8 +278,8 @@ void EglManager::createPBufferSurface() {
EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorGamut) {
initialize();
- wideColorGamut = wideColorGamut && EglExtensions.glColorSpace && EglExtensions.scRGB
- && EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext;
+ wideColorGamut = wideColorGamut && EglExtensions.glColorSpace && EglExtensions.scRGB &&
+ EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext;
// The color space we want to use depends on whether linear blending is turned
// on and whether the app has requested wide color gamut rendering. When wide
@@ -280,10 +303,7 @@ EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorG
// We insert to placeholders to set EGL_GL_COLORSPACE_KHR and its value.
// According to section 3.4.1 of the EGL specification, the attributes
// list is considered empty if the first entry is EGL_NONE
- EGLint attribs[] = {
- EGL_NONE, EGL_NONE,
- EGL_NONE
- };
+ EGLint attribs[] = {EGL_NONE, EGL_NONE, EGL_NONE};
if (EglExtensions.glColorSpace) {
attribs[0] = EGL_GL_COLORSPACE_KHR;
@@ -302,16 +322,17 @@ EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorG
#endif
}
- EGLSurface surface = eglCreateWindowSurface(mEglDisplay,
- wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
+ EGLSurface surface = eglCreateWindowSurface(
+ mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
- "Failed to create EGLSurface for window %p, eglErr = %s",
- (void*) window, eglErrorString());
+ "Failed to create EGLSurface for window %p, eglErr = %s", (void*)window,
+ eglErrorString());
if (mSwapBehavior != SwapBehavior::Preserved) {
- LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) == EGL_FALSE,
+ LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
+ EGL_BUFFER_DESTROYED) == EGL_FALSE,
"Failed to set swap behavior to destroyed for window %p, eglErr = %s",
- (void*) window, eglErrorString());
+ (void*)window, eglErrorString());
}
return surface;
@@ -353,11 +374,11 @@ bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
if (errOut) {
*errOut = eglGetError();
- ALOGW("Failed to make current on surface %p, error=%s",
- (void*)surface, egl_error_str(*errOut));
+ ALOGW("Failed to make current on surface %p, error=%s", (void*)surface,
+ egl_error_str(*errOut));
} else {
- LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
- (void*)surface, eglErrorString());
+ LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", (void*)surface,
+ eglErrorString());
}
}
mCurrentSurface = surface;
@@ -369,21 +390,20 @@ bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
EGLint EglManager::queryBufferAge(EGLSurface surface) {
switch (mSwapBehavior) {
- case SwapBehavior::Discard:
- return 0;
- case SwapBehavior::Preserved:
- return 1;
- case SwapBehavior::BufferAge:
- EGLint bufferAge;
- eglQuerySurface(mEglDisplay, surface, EGL_BUFFER_AGE_EXT, &bufferAge);
- return bufferAge;
+ case SwapBehavior::Discard:
+ return 0;
+ case SwapBehavior::Preserved:
+ return 1;
+ case SwapBehavior::BufferAge:
+ EGLint bufferAge;
+ eglQuerySurface(mEglDisplay, surface, EGL_BUFFER_AGE_EXT, &bufferAge);
+ return bufferAge;
}
return 0;
}
Frame EglManager::beginFrame(EGLSurface surface) {
- LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
- "Tried to beginFrame on EGL_NO_SURFACE!");
+ LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, "Tried to beginFrame on EGL_NO_SURFACE!");
makeCurrent(surface);
Frame frame;
frame.mSurface = surface;
@@ -401,7 +421,7 @@ void EglManager::damageFrame(const Frame& frame, const SkRect& dirty) {
frame.map(dirty, rects);
if (!eglSetDamageRegionKHR(mEglDisplay, frame.mSurface, rects, 1)) {
LOG_ALWAYS_FATAL("Failed to set damage region on surface %p, error=%s",
- (void*)frame.mSurface, eglErrorString());
+ (void*)frame.mSurface, eglErrorString());
}
}
#endif
@@ -412,7 +432,6 @@ bool EglManager::damageRequiresSwap() {
}
bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
-
if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
ATRACE_NAME("Finishing GPU work");
fence();
@@ -420,8 +439,7 @@ bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
EGLint rects[4];
frame.map(screenDirty, rects);
- eglSwapBuffersWithDamageKHR(mEglDisplay, frame.mSurface, rects,
- screenDirty.isEmpty() ? 0 : 1);
+ eglSwapBuffersWithDamageKHR(mEglDisplay, frame.mSurface, rects, screenDirty.isEmpty() ? 0 : 1);
EGLint err = eglGetError();
if (CC_LIKELY(err == EGL_SUCCESS)) {
@@ -431,20 +449,18 @@ bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
// For some reason our surface was destroyed out from under us
// This really shouldn't happen, but if it does we can recover easily
// by just not trying to use the surface anymore
- ALOGW("swapBuffers encountered EGL error %d on %p, halting rendering...",
- err, frame.mSurface);
+ ALOGW("swapBuffers encountered EGL error %d on %p, halting rendering...", err,
+ frame.mSurface);
return false;
}
- LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering",
- err, egl_error_str(err));
+ LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering", err, egl_error_str(err));
// Impossible to hit this, but the compiler doesn't know that
return false;
}
void EglManager::fence() {
EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL);
- eglClientWaitSyncKHR(mEglDisplay, fence,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
+ eglClientWaitSyncKHR(mEglDisplay, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
eglDestroySyncKHR(mEglDisplay, fence);
}
@@ -452,17 +468,17 @@ bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
if (mSwapBehavior != SwapBehavior::Preserved) return false;
bool preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
- preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
+ preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
if (!preserved) {
- ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
- (void*) surface, eglErrorString());
+ ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", (void*)surface,
+ eglErrorString());
// Maybe it's already set?
EGLint swapBehavior;
if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) {
preserved = (swapBehavior == EGL_BUFFER_PRESERVED);
} else {
- ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
- (void*) surface, eglErrorString());
+ ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", (void*)surface,
+ eglErrorString());
}
}
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 2982c23552c9..ef9effbf9953 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -16,9 +16,9 @@
#ifndef EGLMANAGER_H
#define EGLMANAGER_H
-#include <cutils/compiler.h>
#include <EGL/egl.h>
#include <SkRect.h>
+#include <cutils/compiler.h>
#include <ui/GraphicBuffer.h>
#include <utils/StrongPointer.h>
diff --git a/libs/hwui/renderthread/Frame.h b/libs/hwui/renderthread/Frame.h
index 99996fe40626..d266faa4f7c9 100644
--- a/libs/hwui/renderthread/Frame.h
+++ b/libs/hwui/renderthread/Frame.h
@@ -19,7 +19,7 @@
#include <stdint.h>
struct SkRect;
-typedef void *EGLSurface;
+typedef void* EGLSurface;
namespace android {
namespace uirenderer {
@@ -28,9 +28,7 @@ namespace renderthread {
class Frame {
public:
Frame(int32_t width, int32_t height, int32_t bufferAge)
- : mWidth(width)
- , mHeight(height)
- , mBufferAge(bufferAge) { }
+ : mWidth(width), mHeight(height), mBufferAge(bufferAge) {}
int32_t width() const { return mWidth; }
int32_t height() const { return mHeight; }
@@ -57,4 +55,3 @@ private:
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index f9b6e384d211..b1de49733c09 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -17,6 +17,7 @@
#pragma once
#include "FrameInfoVisualizer.h"
+#include "SwapBehavior.h"
#include <SkRect.h>
#include <utils/RefBase.h>
@@ -30,19 +31,11 @@ class Surface;
namespace uirenderer {
class DeferredLayerUpdater;
+class ErrorHandler;
namespace renderthread {
-enum class SwapBehavior {
- kSwap_default,
- kSwap_discardBuffer,
-};
-
-enum class MakeCurrentResult {
- AlreadyCurrent,
- Failed,
- Succeeded
-};
+enum class MakeCurrentResult { AlreadyCurrent, Failed, Succeeded };
enum class ColorMode {
Srgb,
@@ -57,14 +50,13 @@ public:
virtual MakeCurrentResult makeCurrent() = 0;
virtual Frame getFrame() = 0;
virtual bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) = 0;
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
+ bool opaque, bool wideColorGamut, const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) = 0;
virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
+ FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
virtual bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) = 0;
virtual DeferredLayerUpdater* createTextureLayer() = 0;
virtual bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0;
@@ -73,14 +65,15 @@ public:
virtual bool isContextReady() = 0;
virtual void onDestroyHardwareResources() = 0;
virtual void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) = 0;
+ LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo) = 0;
virtual TaskManager* getTaskManager() = 0;
- virtual bool createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) = 0;
+ virtual bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut, ErrorHandler* errorHandler) = 0;
virtual bool pinImages(std::vector<SkImage*>& mutableImages) = 0;
virtual bool pinImages(LsaVector<sk_sp<Bitmap>>& images) = 0;
virtual void unpinImages() = 0;
+ virtual void onPrepareTree() = 0;
virtual ~IRenderPipeline() {}
};
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index 7283eb123d6a..f96001ebdd57 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -20,9 +20,10 @@
#include "EglManager.h"
#include "Frame.h"
#include "GlLayer.h"
+#include "OpenGLReadback.h"
#include "ProfileRenderer.h"
#include "renderstate/RenderState.h"
-#include "OpenGLReadback.h"
+#include "TreeInfo.h"
#include <cutils/properties.h>
#include <strings.h>
@@ -32,9 +33,7 @@ namespace uirenderer {
namespace renderthread {
OpenGLPipeline::OpenGLPipeline(RenderThread& thread)
- : mEglManager(thread.eglManager())
- , mRenderThread(thread) {
-}
+ : mEglManager(thread.eglManager()), mRenderThread(thread) {}
MakeCurrentResult OpenGLPipeline::makeCurrent() {
// TODO: Figure out why this workaround is needed, see b/13913604
@@ -51,23 +50,21 @@ MakeCurrentResult OpenGLPipeline::makeCurrent() {
Frame OpenGLPipeline::getFrame() {
LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
- "drawRenderNode called on a context with no surface!");
+ "drawRenderNode called on a context with no surface!");
return mEglManager.beginFrame(mEglSurface);
}
bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) {
-
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
+ bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) {
mEglManager.damageFrame(frame, dirty);
bool drew = false;
-
auto& caches = Caches::getInstance();
FrameBuilder frameBuilder(dirty, frame.width(), frame.height(), lightGeometry, caches);
@@ -76,8 +73,8 @@ bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const S
frameBuilder.deferRenderNodeScene(renderNodes, contentDrawBounds);
- BakedOpRenderer renderer(caches, mRenderThread.renderState(),
- opaque, wideColorGamut, lightInfo);
+ BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut,
+ lightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
ProfileRenderer profileRenderer(renderer);
profiler->draw(profileRenderer);
@@ -100,8 +97,7 @@ bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const S
}
bool OpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) {
-
+ FrameInfo* currentFrameInfo, bool* requireSwap) {
GL_CHECKPOINT(LOW);
// Even if we decided to cancel the frame, from the perspective of jank
@@ -123,13 +119,14 @@ bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap
layer->updateTexImage();
layer->apply();
return OpenGLReadbackImpl::copyLayerInto(mRenderThread,
- static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
+ static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
}
static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
- SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
- GlLayer* layer = new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha,
- mode, blend);
+ sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode,
+ bool blend) {
+ GlLayer* layer =
+ new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
Caches::getInstance().textureState().activateTexture(0);
layer->generateTexture();
return layer;
@@ -147,7 +144,6 @@ void OpenGLPipeline::onStop() {
}
bool OpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior, ColorMode colorMode) {
-
if (mEglSurface != EGL_NO_SURFACE) {
mEglManager.destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
@@ -184,14 +180,16 @@ void OpenGLPipeline::onDestroyHardwareResources() {
}
void OpenGLPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) {
- static const std::vector< sp<RenderNode> > emptyNodeList;
+ LayerUpdateQueue* layerUpdateQueue, bool opaque,
+ bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo) {
+ static const std::vector<sp<RenderNode>> emptyNodeList;
auto& caches = Caches::getInstance();
FrameBuilder frameBuilder(*layerUpdateQueue, lightGeometry, caches);
layerUpdateQueue->clear();
// TODO: Handle wide color gamut contexts
- BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut, lightInfo);
+ BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut,
+ lightInfo);
LOG_ALWAYS_FATAL_IF(renderer.didDraw(), "shouldn't draw in buildlayer case");
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
}
@@ -205,13 +203,15 @@ static bool layerMatchesWH(OffscreenBuffer* layer, int width, int height) {
}
bool OpenGLPipeline::createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) {
+ const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut,
+ ErrorHandler* errorHandler) {
RenderState& renderState = mRenderThread.renderState();
OffscreenBufferPool& layerPool = renderState.layerPool();
bool transformUpdateNeeded = false;
if (node->getLayer() == nullptr) {
- node->setLayer(layerPool.get(renderState,
- node->getWidth(), node->getHeight(), wideColorGamut));
+ node->setLayer(
+ layerPool.get(renderState, node->getWidth(), node->getHeight(), wideColorGamut));
transformUpdateNeeded = true;
} else if (!layerMatchesWH(node->getLayer(), node->getWidth(), node->getHeight())) {
// TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering)
@@ -231,6 +231,22 @@ bool OpenGLPipeline::createOrUpdateLayer(RenderNode* node,
node->getLayer()->setWindowTransform(windowTransform);
}
+ if (!node->hasLayer()) {
+ Caches::getInstance().dumpMemoryUsage();
+ if (errorHandler) {
+ std::ostringstream err;
+ err << "Unable to create layer for " << node->getName();
+ const int maxTextureSize = Caches::getInstance().maxTextureSize;
+ if (node->getWidth() > maxTextureSize || node->getHeight() > maxTextureSize) {
+ err << ", size " << node->getWidth() << "x" << node->getHeight()
+ << " exceeds max size " << maxTextureSize;
+ } else {
+ err << ", see logcat for more info";
+ }
+ errorHandler->onError(err.str());
+ }
+ }
+
return transformUpdateNeeded;
}
@@ -273,8 +289,7 @@ void OpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor)
class AutoEglFence {
public:
- AutoEglFence(EGLDisplay display)
- : mDisplay(display) {
+ AutoEglFence(EGLDisplay display) : mDisplay(display) {
fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
}
@@ -285,17 +300,17 @@ public:
}
EGLSyncKHR fence = EGL_NO_SYNC_KHR;
+
private:
EGLDisplay mDisplay = EGL_NO_DISPLAY;
};
class AutoEglImage {
public:
- AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
- : mDisplay(display) {
- EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
- image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
+ AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer) : mDisplay(display) {
+ EGLint imageAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+ image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer,
+ imageAttrs);
}
~AutoEglImage() {
@@ -305,21 +320,19 @@ public:
}
EGLImageKHR image = EGL_NO_IMAGE_KHR;
+
private:
EGLDisplay mDisplay = EGL_NO_DISPLAY;
};
class AutoGlTexture {
public:
- AutoGlTexture(uirenderer::Caches& caches)
- : mCaches(caches) {
+ AutoGlTexture(uirenderer::Caches& caches) : mCaches(caches) {
glGenTextures(1, &mTexture);
caches.textureState().bindTexture(mTexture);
}
- ~AutoGlTexture() {
- mCaches.textureState().deleteTexture(mTexture);
- }
+ ~AutoGlTexture() { mCaches.textureState().deleteTexture(mTexture); }
private:
uirenderer::Caches& mCaches;
@@ -327,18 +340,17 @@ private:
};
static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap,
- GraphicBuffer& buffer, GLint format, GLint type) {
+ GraphicBuffer& buffer, GLint format, GLint type) {
EGLDisplay display = eglGetCurrentDisplay();
- LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
- "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
- uirenderer::renderthread::EglManager::eglErrorString());
+ LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+ uirenderer::renderthread::EglManager::eglErrorString());
// We use an EGLImage to access the content of the GraphicBuffer
// The EGL image is later bound to a 2D texture
- EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer.getNativeBuffer();
+ EGLClientBuffer clientBuffer = (EGLClientBuffer)buffer.getNativeBuffer();
AutoEglImage autoImage(display, clientBuffer);
if (autoImage.image == EGL_NO_IMAGE_KHR) {
ALOGW("Could not create EGL image, err =%s",
- uirenderer::renderthread::EglManager::eglErrorString());
+ uirenderer::renderthread::EglManager::eglErrorString());
return false;
}
AutoGlTexture glTexture(caches);
@@ -346,8 +358,8 @@ static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bi
GL_CHECKPOINT(MODERATE);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
- format, type, bitmap.getPixels());
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), format, type,
+ bitmap.getPixels());
GL_CHECKPOINT(MODERATE);
@@ -362,7 +374,7 @@ static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bi
// The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
// pipeline flush (similar to what a glFlush() would do.)
EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
return false;
@@ -373,24 +385,24 @@ static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bi
// TODO: handle SRGB sanely
static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
switch (internalFormat) {
- case GL_LUMINANCE:
- return PIXEL_FORMAT_RGBA_8888;
- case GL_SRGB8_ALPHA8:
- return PIXEL_FORMAT_RGBA_8888;
- case GL_RGBA:
- return PIXEL_FORMAT_RGBA_8888;
- case GL_RGB:
- return PIXEL_FORMAT_RGB_565;
- case GL_RGBA16F:
- return PIXEL_FORMAT_RGBA_FP16;
- default:
- LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
- return PIXEL_FORMAT_UNKNOWN;
+ case GL_LUMINANCE:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_SRGB8_ALPHA8:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_RGBA:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_RGB:
+ return PIXEL_FORMAT_RGB_565;
+ case GL_RGBA16F:
+ return PIXEL_FORMAT_RGBA_FP16;
+ default:
+ LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
+ return PIXEL_FORMAT_UNKNOWN;
}
}
sk_sp<Bitmap> OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread,
- SkBitmap& skBitmap) {
+ SkBitmap& skBitmap) {
renderThread.eglManager().initialize();
uirenderer::Caches& caches = uirenderer::Caches::getInstance();
@@ -404,13 +416,14 @@ sk_sp<Bitmap> OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread,
bool hasLinearBlending = caches.extensions().hasLinearBlending();
GLint format, type, internalFormat;
uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(),
- needSRGB && hasLinearBlending, &internalFormat, &format, &type);
+ needSRGB && hasLinearBlending, &internalFormat,
+ &format, &type);
PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
- sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
- GraphicBuffer::USAGE_HW_TEXTURE |
- GraphicBuffer::USAGE_SW_WRITE_NEVER |
- GraphicBuffer::USAGE_SW_READ_NEVER,
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ info.width(), info.height(), pixelFormat,
+ GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
+ GraphicBuffer::USAGE_SW_READ_NEVER,
std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]");
status_t error = buffer->initCheck();
@@ -420,8 +433,8 @@ sk_sp<Bitmap> OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread,
}
SkBitmap bitmap;
- if (CC_UNLIKELY(uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(),
- hasLinearBlending))) {
+ if (CC_UNLIKELY(
+ uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(), hasLinearBlending))) {
sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
} else {
diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h
index 4ca19fb6245c..9859e931fd85 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.h
+++ b/libs/hwui/renderthread/OpenGLPipeline.h
@@ -16,9 +16,9 @@
#pragma once
-#include "CanvasContext.h"
#include "BakedOpDispatcher.h"
#include "BakedOpRenderer.h"
+#include "CanvasContext.h"
#include "FrameBuilder.h"
#include "IRenderPipeline.h"
@@ -34,14 +34,13 @@ public:
MakeCurrentResult makeCurrent() override;
Frame getFrame() override;
bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
- const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue,
- const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo,
- const std::vector< sp<RenderNode> >& renderNodes,
- FrameInfoVisualizer* profiler) override;
+ const FrameBuilder::LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+ const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector<sp<RenderNode>>& renderNodes,
+ FrameInfoVisualizer* profiler) override;
bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
- FrameInfo* currentFrameInfo, bool* requireSwap) override;
+ FrameInfo* currentFrameInfo, bool* requireSwap) override;
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) override;
@@ -50,19 +49,19 @@ public:
bool isContextReady() override;
void onDestroyHardwareResources() override;
void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
- LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
- const BakedOpRenderer::LightInfo& lightInfo) override;
+ LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
+ const BakedOpRenderer::LightInfo& lightInfo) override;
TaskManager* getTaskManager() override;
- bool createOrUpdateLayer(RenderNode* node,
- const DamageAccumulator& damageAccumulator, bool wideColorGamut) override;
+ bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+ bool wideColorGamut, ErrorHandler* errorHandler) override;
bool pinImages(std::vector<SkImage*>& mutableImages) override { return false; }
bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override;
void unpinImages() override;
+ void onPrepareTree() override {}
static void destroyLayer(RenderNode* node);
static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap);
static void invokeFunctor(const RenderThread& thread, Functor* functor);
- static sk_sp<Bitmap> allocateHardwareBitmap(RenderThread& thread,
- SkBitmap& skBitmap);
+ static sk_sp<Bitmap> allocateHardwareBitmap(RenderThread& thread, SkBitmap& skBitmap);
private:
EglManager& mEglManager;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 9048bd14b35c..59048be768e9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -22,11 +22,11 @@
#include "Readback.h"
#include "Rect.h"
#include "pipeline/skia/VectorDrawableAtlas.h"
+#include "renderstate/RenderState.h"
#include "renderthread/CanvasContext.h"
#include "renderthread/EglManager.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
-#include "renderstate/RenderState.h"
#include "utils/Macros.h"
#include "utils/TimeUtils.h"
@@ -36,46 +36,12 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-#define ARGS(method) method ## Args
-
-#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,)
-#define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,)
-#define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,)
-#define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,)
-#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,)
-#define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,)
-#define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,)
-#define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,)
-#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \
- typedef struct { \
- a1; a2; a3; a4; a5; a6; a7; a8; \
- } ARGS(name); \
- static_assert(std::is_trivially_destructible<ARGS(name)>::value, \
- "Error, ARGS must be trivially destructible!"); \
- static void* Bridge_ ## name(ARGS(name)* args)
-
-#define SETUP_TASK(method) \
- LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \
- "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \
- METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \
- MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
- ARGS(method) *args = (ARGS(method) *) task->payload()
-
-CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory) {
- return CanvasContext::create(*args->thread, args->translucent,
- args->rootRenderNode, args->contextFactory);
-}
-
-RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
- : mRenderThread(RenderThread::getInstance())
- , mContext(nullptr) {
- SETUP_TASK(createContext);
- args->translucent = translucent;
- args->rootRenderNode = rootRenderNode;
- args->thread = &mRenderThread;
- args->contextFactory = contextFactory;
- mContext = (CanvasContext*) postAndWait(task);
+RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory)
+ : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
+ mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
+ return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
+ });
mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}
@@ -83,162 +49,72 @@ RenderProxy::~RenderProxy() {
destroyContext();
}
-CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
- delete args->context;
- return nullptr;
-}
-
void RenderProxy::destroyContext() {
if (mContext) {
- SETUP_TASK(destroyContext);
- args->context = mContext;
- mContext = nullptr;
mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
// This is also a fence as we need to be certain that there are no
// outstanding mDrawFrame tasks posted before it is destroyed
- postAndWait(task);
+ mRenderThread.queue().runSync([this]() { delete mContext; });
+ mContext = nullptr;
}
}
-CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
- args->context->setSwapBehavior(args->swapBehavior);
- return nullptr;
-}
-
void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
- SETUP_TASK(setSwapBehavior);
- args->context = mContext;
- args->swapBehavior = swapBehavior;
- post(task);
-}
-
-CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
- bool needsRedraw = false;
- if (Caches::hasInstance()) {
- needsRedraw = Properties::load();
- }
- if (args->context->profiler().consumeProperties()) {
- needsRedraw = true;
- }
- return (void*) needsRedraw;
+ mRenderThread.queue().post([this, swapBehavior]() { mContext->setSwapBehavior(swapBehavior); });
}
bool RenderProxy::loadSystemProperties() {
- SETUP_TASK(loadSystemProperties);
- args->context = mContext;
- return (bool) postAndWait(task);
-}
-
-CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) {
- args->context->setName(std::string(args->name));
- return nullptr;
+ return mRenderThread.queue().runSync([this]() -> bool {
+ bool needsRedraw = false;
+ if (Caches::hasInstance()) {
+ needsRedraw = Properties::load();
+ }
+ if (mContext->profiler().consumeProperties()) {
+ needsRedraw = true;
+ }
+ return needsRedraw;
+ });
}
void RenderProxy::setName(const char* name) {
- SETUP_TASK(setName);
- args->context = mContext;
- args->name = name;
- postAndWait(task); // block since name/value pointers owned by caller
-}
-
-CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) {
- args->context->initialize(args->surface);
- return nullptr;
+ // block since name/value pointers owned by caller
+ // TODO: Support move arguments
+ mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
}
void RenderProxy::initialize(const sp<Surface>& surface) {
- SETUP_TASK(initialize);
- args->context = mContext;
- args->surface = surface.get();
- post(task);
-}
-
-CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) {
- args->context->updateSurface(args->surface);
- return nullptr;
+ mRenderThread.queue().post(
+ [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
}
void RenderProxy::updateSurface(const sp<Surface>& surface) {
- SETUP_TASK(updateSurface);
- args->context = mContext;
- args->surface = surface.get();
- post(task);
-}
-
-CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
- return (void*) args->context->pauseSurface(args->surface);
+ mRenderThread.queue().post(
+ [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
}
bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
- SETUP_TASK(pauseSurface);
- args->context = mContext;
- args->surface = surface.get();
- return (bool) postAndWait(task);
-}
-
-CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) {
- args->context->setStopped(args->stopped);
- return nullptr;
+ return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
}
void RenderProxy::setStopped(bool stopped) {
- SETUP_TASK(setStopped);
- args->context = mContext;
- args->stopped = stopped;
- postAndWait(task);
-}
-
-CREATE_BRIDGE4(setup, CanvasContext* context,
- float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
- args->context->setup(args->lightRadius,
- args->ambientShadowAlpha, args->spotShadowAlpha);
- return nullptr;
+ mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
}
-void RenderProxy::setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
- SETUP_TASK(setup);
- args->context = mContext;
- args->lightRadius = lightRadius;
- args->ambientShadowAlpha = ambientShadowAlpha;
- args->spotShadowAlpha = spotShadowAlpha;
- post(task);
-}
-
-CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) {
- args->context->setLightCenter(args->lightCenter);
- return nullptr;
+void RenderProxy::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+ mRenderThread.queue().post(
+ [=]() { mContext->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); });
}
void RenderProxy::setLightCenter(const Vector3& lightCenter) {
- SETUP_TASK(setLightCenter);
- args->context = mContext;
- args->lightCenter = lightCenter;
- post(task);
-}
-
-CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
- args->context->setOpaque(args->opaque);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->setLightCenter(lightCenter); });
}
void RenderProxy::setOpaque(bool opaque) {
- SETUP_TASK(setOpaque);
- args->context = mContext;
- args->opaque = opaque;
- post(task);
-}
-
-CREATE_BRIDGE2(setWideGamut, CanvasContext* context, bool wideGamut) {
- args->context->setWideGamut(args->wideGamut);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->setOpaque(opaque); });
}
void RenderProxy::setWideGamut(bool wideGamut) {
- SETUP_TASK(setWideGamut);
- args->context = mContext;
- args->wideGamut = wideGamut;
- post(task);
+ mRenderThread.queue().post([=]() { mContext->setWideGamut(wideGamut); });
}
int64_t* RenderProxy::frameInfo() {
@@ -249,77 +125,40 @@ int RenderProxy::syncAndDrawFrame() {
return mDrawFrameTask.drawFrame();
}
-CREATE_BRIDGE1(destroy, CanvasContext* context) {
- args->context->destroy();
- return nullptr;
-}
-
void RenderProxy::destroy() {
- SETUP_TASK(destroy);
- args->context = mContext;
// destroyCanvasAndSurface() needs a fence as when it returns the
// underlying BufferQueue is going to be released from under
// the render thread.
- postAndWait(task);
-}
-
-CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
- CanvasContext::invokeFunctor(*args->thread, args->functor);
- return nullptr;
+ mRenderThread.queue().runSync([=]() { mContext->destroy(); });
}
void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
ATRACE_CALL();
RenderThread& thread = RenderThread::getInstance();
- SETUP_TASK(invokeFunctor);
- args->thread = &thread;
- args->functor = functor;
+ auto invoke = [&thread, functor]() { CanvasContext::invokeFunctor(thread, functor); };
if (waitForCompletion) {
// waitForCompletion = true is expected to be fairly rare and only
// happen in destruction. Thus it should be fine to temporarily
// create a Mutex
- staticPostAndWait(task);
+ thread.queue().runSync(std::move(invoke));
} else {
- thread.queue(task);
+ thread.queue().post(std::move(invoke));
}
}
-CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
- return args->context->createTextureLayer();
-}
-
DeferredLayerUpdater* RenderProxy::createTextureLayer() {
- SETUP_TASK(createTextureLayer);
- args->context = mContext;
- void* retval = postAndWait(task);
- DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
- return layer;
-}
-
-CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
- args->context->buildLayer(args->node);
- return nullptr;
+ return mRenderThread.queue().runSync([this]() -> auto {
+ return mContext->createTextureLayer();
+ });
}
void RenderProxy::buildLayer(RenderNode* node) {
- SETUP_TASK(buildLayer);
- args->context = mContext;
- args->node = node;
- postAndWait(task);
-}
-
-CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
- SkBitmap* bitmap) {
- bool success = args->context->copyLayerInto(args->layer, args->bitmap);
- return (void*) success;
+ mRenderThread.queue().runSync([&]() { mContext->buildLayer(node); });
}
bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
- SETUP_TASK(copyLayerInto);
- args->context = mContext;
- args->layer = layer;
- args->bitmap = &bitmap;
- return (bool) postAndWait(task);
+ return mRenderThread.queue().runSync(
+ [&]() -> bool { return mContext->copyLayerInto(layer, &bitmap); });
}
void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -330,302 +169,137 @@ void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
mDrawFrameTask.removeLayerUpdate(layer);
}
-CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
- args->layer->detachSurfaceTexture();
- return nullptr;
-}
-
void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
- SETUP_TASK(detachSurfaceTexture);
- args->layer = layer;
- postAndWait(task);
-}
-
-CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
- args->context->destroyHardwareResources();
- return nullptr;
+ return mRenderThread.queue().runSync([&]() { layer->detachSurfaceTexture(); });
}
void RenderProxy::destroyHardwareResources() {
- SETUP_TASK(destroyHardwareResources);
- args->context = mContext;
- postAndWait(task);
-}
-
-CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
- CanvasContext::trimMemory(*args->thread, args->level);
- return nullptr;
+ return mRenderThread.queue().runSync([&]() { mContext->destroyHardwareResources(); });
}
void RenderProxy::trimMemory(int level) {
// Avoid creating a RenderThread to do a trimMemory.
if (RenderThread::hasInstance()) {
RenderThread& thread = RenderThread::getInstance();
- SETUP_TASK(trimMemory);
- args->thread = &thread;
- args->level = level;
- thread.queue(task);
+ thread.queue().post([&thread, level]() { CanvasContext::trimMemory(thread, level); });
}
}
-CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
- Properties::overrideProperty(args->name, args->value);
- return nullptr;
-}
-
void RenderProxy::overrideProperty(const char* name, const char* value) {
- SETUP_TASK(overrideProperty);
- args->name = name;
- args->value = value;
- staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller
-}
-
-CREATE_BRIDGE0(fence) {
- // Intentionally empty
- return nullptr;
+ // expensive, but block here since name/value pointers owned by caller
+ RenderThread::getInstance().queue().runSync(
+ [&]() { Properties::overrideProperty(name, value); });
}
-template <typename T>
-void UNUSED(T t) {}
-
void RenderProxy::fence() {
- SETUP_TASK(fence);
- UNUSED(args);
- postAndWait(task);
+ mRenderThread.queue().runSync([]() {});
}
void RenderProxy::staticFence() {
- SETUP_TASK(fence);
- UNUSED(args);
- staticPostAndWait(task);
-}
-
-CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
- args->context->stopDrawing();
- return nullptr;
+ RenderThread::getInstance().queue().runSync([]() {});
}
void RenderProxy::stopDrawing() {
- SETUP_TASK(stopDrawing);
- args->context = mContext;
- postAndWait(task);
-}
-
-CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
- args->context->notifyFramePending();
- return nullptr;
+ mRenderThread.queue().runSync([this]() { mContext->stopDrawing(); });
}
void RenderProxy::notifyFramePending() {
- SETUP_TASK(notifyFramePending);
- args->context = mContext;
- mRenderThread.queueAtFront(task);
-}
-
-CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread,
- int fd, int dumpFlags) {
- args->context->profiler().dumpData(args->fd);
- if (args->dumpFlags & DumpFlags::FrameStats) {
- args->context->dumpFrames(args->fd);
- }
- if (args->dumpFlags & DumpFlags::JankStats) {
- args->thread->globalProfileData()->dump(args->fd);
- }
- if (args->dumpFlags & DumpFlags::Reset) {
- args->context->resetFrameStats();
- }
- return nullptr;
+ mRenderThread.queue().post([this]() { mContext->notifyFramePending(); });
}
void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
- SETUP_TASK(dumpProfileInfo);
- args->context = mContext;
- args->thread = &mRenderThread;
- args->fd = fd;
- args->dumpFlags = dumpFlags;
- postAndWait(task);
-}
-
-CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
- args->context->resetFrameStats();
- return nullptr;
+ mRenderThread.queue().runSync([&]() {
+ mContext->profiler().dumpData(fd);
+ if (dumpFlags & DumpFlags::FrameStats) {
+ mContext->dumpFrames(fd);
+ }
+ if (dumpFlags & DumpFlags::JankStats) {
+ mRenderThread.globalProfileData()->dump(fd);
+ }
+ if (dumpFlags & DumpFlags::Reset) {
+ mContext->resetFrameStats();
+ }
+ });
}
void RenderProxy::resetProfileInfo() {
- SETUP_TASK(resetProfileInfo);
- args->context = mContext;
- postAndWait(task);
-}
-
-CREATE_BRIDGE2(frameTimePercentile, RenderThread* thread, int percentile) {
- return reinterpret_cast<void*>(static_cast<uintptr_t>(
- args->thread->globalProfileData()->findPercentile(args->percentile)));
-}
-
-uint32_t RenderProxy::frameTimePercentile(int p) {
- SETUP_TASK(frameTimePercentile);
- args->thread = &mRenderThread;
- args->percentile = p;
- return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
- postAndWait(task)));
+ mRenderThread.queue().runSync([=]() { mContext->resetFrameStats(); });
}
-CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
- args->thread->dumpGraphicsMemory(args->fd);
- return nullptr;
+uint32_t RenderProxy::frameTimePercentile(int percentile) {
+ return mRenderThread.queue().runSync([&]() -> auto {
+ return mRenderThread.globalProfileData()->findPercentile(percentile);
+ });
}
void RenderProxy::dumpGraphicsMemory(int fd) {
- if (!RenderThread::hasInstance()) return;
- SETUP_TASK(dumpGraphicsMemory);
- args->fd = fd;
- args->thread = &RenderThread::getInstance();
- staticPostAndWait(task);
-}
-
-CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
- args->thread->globalProfileData().switchStorageToAshmem(args->fd);
- close(args->fd);
- return nullptr;
+ auto& thread = RenderThread::getInstance();
+ thread.queue().runSync([&]() { thread.dumpGraphicsMemory(fd); });
}
void RenderProxy::setProcessStatsBuffer(int fd) {
- SETUP_TASK(setProcessStatsBuffer);
auto& rt = RenderThread::getInstance();
- args->thread = &rt;
- args->fd = dup(fd);
- rt.queue(task);
-}
-
-CREATE_BRIDGE1(rotateProcessStatsBuffer, RenderThread* thread) {
- args->thread->globalProfileData().rotateStorage();
- return nullptr;
+ rt.queue().post([&rt, fd = dup(fd) ]() {
+ rt.globalProfileData().switchStorageToAshmem(fd);
+ close(fd);
+ });
}
void RenderProxy::rotateProcessStatsBuffer() {
- SETUP_TASK(rotateProcessStatsBuffer);
auto& rt = RenderThread::getInstance();
- args->thread = &rt;
- rt.queue(task);
+ rt.queue().post([&rt]() { rt.globalProfileData().rotateStorage(); });
}
int RenderProxy::getRenderThreadTid() {
return mRenderThread.getTid();
}
-CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) {
- args->context->addRenderNode(args->node, args->placeFront);
- return nullptr;
-}
-
void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
- SETUP_TASK(addRenderNode);
- args->context = mContext;
- args->node = node;
- args->placeFront = placeFront;
- post(task);
-}
-
-CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) {
- args->context->removeRenderNode(args->node);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->addRenderNode(node, placeFront); });
}
void RenderProxy::removeRenderNode(RenderNode* node) {
- SETUP_TASK(removeRenderNode);
- args->context = mContext;
- args->node = node;
- post(task);
-}
-
-CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) {
- args->context->prepareAndDraw(args->node);
- return nullptr;
+ mRenderThread.queue().post([=]() { mContext->removeRenderNode(node); });
}
void RenderProxy::drawRenderNode(RenderNode* node) {
- SETUP_TASK(drawRenderNode);
- args->context = mContext;
- args->node = node;
- // Be pseudo-thread-safe and don't use any member variables
- staticPostAndWait(task);
+ mRenderThread.queue().runSync([=]() { mContext->prepareAndDraw(node); });
}
void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
mDrawFrameTask.setContentDrawBounds(left, top, right, bottom);
}
-CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
- args->context->serializeDisplayListTree();
- return nullptr;
+void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
+ mDrawFrameTask.setFrameCallback(std::move(callback));
}
-void RenderProxy::serializeDisplayListTree() {
- SETUP_TASK(serializeDisplayListTree);
- args->context = mContext;
- post(task);
-}
-
-CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context,
- FrameMetricsObserver* frameStatsObserver) {
- args->context->addFrameMetricsObserver(args->frameStatsObserver);
- if (args->frameStatsObserver != nullptr) {
- args->frameStatsObserver->decStrong(args->context);
- }
- return nullptr;
-}
-
-void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) {
- SETUP_TASK(addFrameMetricsObserver);
- args->context = mContext;
- args->frameStatsObserver = observer;
- if (observer != nullptr) {
- observer->incStrong(mContext);
- }
- post(task);
-}
-
-CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context,
- FrameMetricsObserver* frameStatsObserver) {
- args->context->removeFrameMetricsObserver(args->frameStatsObserver);
- if (args->frameStatsObserver != nullptr) {
- args->frameStatsObserver->decStrong(args->context);
- }
- return nullptr;
+void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+ mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
}
-void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
- SETUP_TASK(removeFrameMetricsObserver);
- args->context = mContext;
- args->frameStatsObserver = observer;
- if (observer != nullptr) {
- observer->incStrong(mContext);
- }
- post(task);
+void RenderProxy::serializeDisplayListTree() {
+ mRenderThread.queue().post([=]() { mContext->serializeDisplayListTree(); });
}
-CREATE_BRIDGE4(copySurfaceInto, RenderThread* thread,
- Surface* surface, Rect srcRect, SkBitmap* bitmap) {
- return (void*)args->thread->readback().copySurfaceInto(*args->surface,
- args->srcRect, args->bitmap);
+void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
+ mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+ mContext->addFrameMetricsObserver(observer.get());
+ });
}
-int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top,
- int right, int bottom, SkBitmap* bitmap) {
- SETUP_TASK(copySurfaceInto);
- args->bitmap = bitmap;
- args->surface = surface.get();
- args->thread = &RenderThread::getInstance();
- args->srcRect.set(left, top, right, bottom);
- return static_cast<int>(
- reinterpret_cast<intptr_t>( staticPostAndWait(task) ));
+void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
+ mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+ mContext->removeFrameMetricsObserver(observer.get());
+ });
}
-CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, Bitmap* bitmap) {
- CanvasContext::prepareToDraw(*args->thread, args->bitmap);
- args->bitmap->unref();
- args->bitmap = nullptr;
- return nullptr;
+int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom,
+ SkBitmap* bitmap) {
+ auto& thread = RenderThread::getInstance();
+ return static_cast<int>(thread.queue().runSync([&]() -> auto {
+ return thread.readback().copySurfaceInto(*surface, Rect(left, top, right, bottom), bitmap);
+ }));
}
void RenderProxy::prepareToDraw(Bitmap& bitmap) {
@@ -635,10 +309,11 @@ void RenderProxy::prepareToDraw(Bitmap& bitmap) {
// window or not.
if (!RenderThread::hasInstance()) return;
RenderThread* renderThread = &RenderThread::getInstance();
- SETUP_TASK(prepareToDraw);
- args->thread = renderThread;
bitmap.ref();
- args->bitmap = &bitmap;
+ auto task = [renderThread, &bitmap]() {
+ CanvasContext::prepareToDraw(*renderThread, &bitmap);
+ bitmap.unref();
+ };
nsecs_t lastVsync = renderThread->timeLord().latestVsync();
nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos();
nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC);
@@ -648,97 +323,59 @@ void RenderProxy::prepareToDraw(Bitmap& bitmap) {
// TODO: Make this concept a first-class supported thing? RT could use
// knowledge of pending draws to better schedule this task
if (timeToNextVsync > -6_ms && timeToNextVsync < 1_ms) {
- renderThread->queueAt(task, estimatedNextVsync + 8_ms);
+ renderThread->queue().postAt(estimatedNextVsync + 8_ms, task);
} else {
- renderThread->queue(task);
+ renderThread->queue().post(task);
}
}
-CREATE_BRIDGE2(allocateHardwareBitmap, RenderThread* thread, SkBitmap* bitmap) {
- sk_sp<Bitmap> hardwareBitmap = args->thread->allocateHardwareBitmap(*args->bitmap);
- return hardwareBitmap.release();
-}
-
sk_sp<Bitmap> RenderProxy::allocateHardwareBitmap(SkBitmap& bitmap) {
- SETUP_TASK(allocateHardwareBitmap);
- args->bitmap = &bitmap;
- args->thread = &RenderThread::getInstance();
- sk_sp<Bitmap> hardwareBitmap(reinterpret_cast<Bitmap*>(staticPostAndWait(task)));
- return hardwareBitmap;
-}
-
-CREATE_BRIDGE3(copyGraphicBufferInto, RenderThread* thread, GraphicBuffer* buffer, SkBitmap* bitmap) {
- return (void*) args->thread->readback().copyGraphicBufferInto(args->buffer, args->bitmap);
+ auto& thread = RenderThread::getInstance();
+ return thread.queue().runSync([&]() -> auto { return thread.allocateHardwareBitmap(bitmap); });
}
int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) {
RenderThread& thread = RenderThread::getInstance();
if (Properties::isSkiaEnabled() && gettid() == thread.getTid()) {
- //TODO: fix everything that hits this. We should never be triggering a readback ourselves.
- return (int) thread.readback().copyGraphicBufferInto(buffer, bitmap);
+ // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
+ return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
} else {
- SETUP_TASK(copyGraphicBufferInto);
- args->thread = &thread;
- args->bitmap = bitmap;
- args->buffer = buffer;
- return static_cast<int>(reinterpret_cast<intptr_t>(staticPostAndWait(task)));
+ return thread.queue().runSync([&]() -> int {
+ return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
+ });
}
}
-CREATE_BRIDGE2(onBitmapDestroyed, RenderThread* thread, uint32_t pixelRefId) {
- args->thread->renderState().onBitmapDestroyed(args->pixelRefId);
- return nullptr;
-}
-
void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) {
if (!RenderThread::hasInstance()) return;
- SETUP_TASK(onBitmapDestroyed);
RenderThread& thread = RenderThread::getInstance();
- args->thread = &thread;
- args->pixelRefId = pixelRefId;
- thread.queue(task);
+ thread.queue().post(
+ [&thread, pixelRefId]() { thread.renderState().onBitmapDestroyed(pixelRefId); });
}
void RenderProxy::disableVsync() {
Properties::disableVsync = true;
}
-void RenderProxy::post(RenderTask* task) {
- mRenderThread.queue(task);
-}
-
-CREATE_BRIDGE1(repackVectorDrawableAtlas, RenderThread* thread) {
- args->thread->cacheManager().acquireVectorDrawableAtlas()->repackIfNeeded(
- args->thread->getGrContext());
- return nullptr;
-}
-
void RenderProxy::repackVectorDrawableAtlas() {
RenderThread& thread = RenderThread::getInstance();
- SETUP_TASK(repackVectorDrawableAtlas);
- args->thread = &thread;
- thread.queue(task);
-}
-
-void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
- void* retval;
- task->setReturnPtr(&retval);
- SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
- AutoMutex _lock(mSyncMutex);
- mRenderThread.queue(&syncTask);
- while (!syncTask.hasRun()) {
- mSyncCondition.wait(mSyncMutex);
- }
- return retval;
+ thread.queue().post([&thread]() {
+ // The context may be null if trimMemory executed, but then the atlas was deleted too.
+ if (thread.getGrContext() != nullptr) {
+ thread.cacheManager().acquireVectorDrawableAtlas()->repackIfNeeded(
+ thread.getGrContext());
+ }
+ });
}
-void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
+void RenderProxy::releaseVDAtlasEntries() {
RenderThread& thread = RenderThread::getInstance();
- LOG_ALWAYS_FATAL_IF(gettid() == thread.getTid());
- void* retval;
- task->setReturnPtr(&retval);
- thread.queueAndWait(task);
- return retval;
+ thread.queue().post([&thread]() {
+ // The context may be null if trimMemory executed, but then the atlas was deleted too.
+ if (thread.getGrContext() != nullptr) {
+ thread.cacheManager().acquireVectorDrawableAtlas()->delayedReleaseEntries();
+ }
+ });
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 06eaebd066ee..ad534f0d96b5 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -17,22 +17,16 @@
#ifndef RENDERPROXY_H_
#define RENDERPROXY_H_
-#include "RenderTask.h"
-
-#include <cutils/compiler.h>
-#include <EGL/egl.h>
#include <SkBitmap.h>
-#include <utils/Condition.h>
+#include <cutils/compiler.h>
+#include <gui/Surface.h>
#include <utils/Functor.h>
-#include <utils/Mutex.h>
-#include <utils/Timers.h>
-#include <utils/StrongPointer.h>
-#include "../Caches.h"
#include "../FrameMetricsObserver.h"
#include "../IContextFactory.h"
-#include "CanvasContext.h"
#include "DrawFrameTask.h"
+#include "SwapBehavior.h"
+#include "hwui/Bitmap.h"
namespace android {
class GraphicBuffer;
@@ -41,22 +35,20 @@ namespace uirenderer {
class DeferredLayerUpdater;
class RenderNode;
-class DisplayList;
-class Layer;
class Rect;
namespace renderthread {
-class ErrorChannel;
+class CanvasContext;
class RenderThread;
class RenderProxyBridge;
namespace DumpFlags {
- enum {
- FrameStats = 1 << 0,
- Reset = 1 << 1,
- JankStats = 1 << 2,
- };
+enum {
+ FrameStats = 1 << 0,
+ Reset = 1 << 1,
+ JankStats = 1 << 2,
+};
};
/*
@@ -81,8 +73,7 @@ public:
ANDROID_API void updateSurface(const sp<Surface>& surface);
ANDROID_API bool pauseSurface(const sp<Surface>& surface);
ANDROID_API void setStopped(bool stopped);
- ANDROID_API void setup(float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ ANDROID_API void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
ANDROID_API void setLightCenter(const Vector3& lightCenter);
ANDROID_API void setOpaque(bool opaque);
ANDROID_API void setWideGamut(bool wideGamut);
@@ -124,13 +115,15 @@ public:
ANDROID_API void removeRenderNode(RenderNode* node);
ANDROID_API void drawRenderNode(RenderNode* node);
ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom);
+ ANDROID_API void setFrameCallback(std::function<void(int64_t)>&& callback);
+ ANDROID_API void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API long getDroppedFrameReportCount();
- ANDROID_API static int copySurfaceInto(sp<Surface>& surface,
- int left, int top, int right, int bottom, SkBitmap* bitmap);
+ ANDROID_API static int copySurfaceInto(sp<Surface>& surface, int left, int top, int right,
+ int bottom, SkBitmap* bitmap);
ANDROID_API static void prepareToDraw(Bitmap& bitmap);
static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
@@ -143,22 +136,16 @@ public:
static void repackVectorDrawableAtlas();
+ static void releaseVDAtlasEntries();
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
DrawFrameTask mDrawFrameTask;
- Mutex mSyncMutex;
- Condition mSyncCondition;
-
void destroyContext();
- void post(RenderTask* task);
- void* postAndWait(MethodInvokeRenderTask* task);
-
- static void* staticPostAndWait(MethodInvokeRenderTask* task);
-
// Friend class to help with bridging
friend class RenderProxyBridge;
};
diff --git a/libs/hwui/renderthread/RenderTask.h b/libs/hwui/renderthread/RenderTask.h
index a7acf91cbdb1..c56a3578ad58 100644
--- a/libs/hwui/renderthread/RenderTask.h
+++ b/libs/hwui/renderthread/RenderTask.h
@@ -53,7 +53,7 @@ public:
ANDROID_API virtual void run() = 0;
RenderTask* mNext;
- nsecs_t mRunAt; // nano-seconds on the SYSTEM_TIME_MONOTONIC clock
+ nsecs_t mRunAt; // nano-seconds on the SYSTEM_TIME_MONOTONIC clock
};
class SignalingRenderTask : public RenderTask {
@@ -75,8 +75,7 @@ typedef void* (*RunnableMethod)(void* data);
class MethodInvokeRenderTask : public RenderTask {
public:
- explicit MethodInvokeRenderTask(RunnableMethod method)
- : mMethod(method), mReturnPtr(nullptr) {}
+ explicit MethodInvokeRenderTask(RunnableMethod method) : mMethod(method), mReturnPtr(nullptr) {}
void* payload() { return mData; }
void setReturnPtr(void** retptr) { mReturnPtr = retptr; }
@@ -89,6 +88,7 @@ public:
// Commit suicide
delete this;
}
+
private:
RunnableMethod mMethod;
char mData[METHOD_INVOKE_PAYLOAD_SIZE];
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index bd34eb80dee8..6a2a025da121 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,22 +16,23 @@
#include "RenderThread.h"
-#include "hwui/Bitmap.h"
-#include "renderstate/RenderState.h"
-#include "renderthread/OpenGLPipeline.h"
-#include "pipeline/skia/SkiaOpenGLReadback.h"
-#include "pipeline/skia/SkiaOpenGLPipeline.h"
-#include "pipeline/skia/SkiaVulkanPipeline.h"
#include "CanvasContext.h"
+#include "DeviceInfo.h"
#include "EglManager.h"
#include "OpenGLReadback.h"
#include "RenderProxy.h"
#include "VulkanManager.h"
+#include "hwui/Bitmap.h"
+#include "pipeline/skia/SkiaOpenGLPipeline.h"
+#include "pipeline/skia/SkiaOpenGLReadback.h"
+#include "pipeline/skia/SkiaVulkanReadback.h"
+#include "pipeline/skia/SkiaVulkanPipeline.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/OpenGLPipeline.h"
#include "utils/FatVector.h"
+#include "utils/TimeUtils.h"
#include <gui/DisplayEventReceiver.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
#include <sys/resource.h>
#include <utils/Condition.h>
#include <utils/Log.h>
@@ -49,107 +50,71 @@ static const size_t EVENT_BUFFER_SIZE = 100;
// Slight delay to give the UI time to push us a new frame before we replay
static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4);
-TaskQueue::TaskQueue() : mHead(nullptr), mTail(nullptr) {}
+static bool gHasRenderThreadInstance = false;
-RenderTask* TaskQueue::next() {
- RenderTask* ret = mHead;
- if (ret) {
- mHead = ret->mNext;
- if (!mHead) {
- mTail = nullptr;
- }
- ret->mNext = nullptr;
- }
- return ret;
-}
+static void (*gOnStartHook)() = nullptr;
-RenderTask* TaskQueue::peek() {
- return mHead;
-}
+class DisplayEventReceiverWrapper : public VsyncSource {
+public:
+ DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver)
+ : mDisplayEventReceiver(std::move(receiver)) {}
-void TaskQueue::queue(RenderTask* task) {
- // Since the RenderTask itself forms the linked list it is not allowed
- // to have the same task queued twice
- LOG_ALWAYS_FATAL_IF(task->mNext || mTail == task, "Task is already in the queue!");
- if (mTail) {
- // Fast path if we can just append
- if (mTail->mRunAt <= task->mRunAt) {
- mTail->mNext = task;
- mTail = task;
- } else {
- // Need to find the proper insertion point
- RenderTask* previous = nullptr;
- RenderTask* next = mHead;
- while (next && next->mRunAt <= task->mRunAt) {
- previous = next;
- next = next->mNext;
- }
- if (!previous) {
- task->mNext = mHead;
- mHead = task;
- } else {
- previous->mNext = task;
- if (next) {
- task->mNext = next;
- } else {
- mTail = task;
+ virtual void requestNextVsync() override {
+ status_t status = mDisplayEventReceiver->requestNextVsync();
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
+ }
+
+ virtual nsecs_t latestVsyncEvent() override {
+ DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
+ nsecs_t latest = 0;
+ ssize_t n;
+ while ((n = mDisplayEventReceiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
+ for (ssize_t i = 0; i < n; i++) {
+ const DisplayEventReceiver::Event& ev = buf[i];
+ switch (ev.header.type) {
+ case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ latest = ev.header.timestamp;
+ break;
}
}
}
- } else {
- mTail = mHead = task;
+ if (n < 0) {
+ ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
+ }
+ return latest;
}
-}
-void TaskQueue::queueAtFront(RenderTask* task) {
- LOG_ALWAYS_FATAL_IF(task->mNext || mHead == task, "Task is already in the queue!");
- if (mTail) {
- task->mNext = mHead;
- mHead = task;
- } else {
- mTail = mHead = task;
- }
-}
+private:
+ std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+};
-void TaskQueue::remove(RenderTask* task) {
- // TaskQueue is strict here to enforce that users are keeping track of
- // their RenderTasks due to how their memory is managed
- LOG_ALWAYS_FATAL_IF(!task->mNext && mTail != task,
- "Cannot remove a task that isn't in the queue!");
+class DummyVsyncSource : public VsyncSource {
+public:
+ DummyVsyncSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
- // If task is the head we can just call next() to pop it off
- // Otherwise we need to scan through to find the task before it
- if (peek() == task) {
- next();
- } else {
- RenderTask* previous = mHead;
- while (previous->mNext != task) {
- previous = previous->mNext;
- }
- previous->mNext = task->mNext;
- if (mTail == task) {
- mTail = previous;
- }
+ virtual void requestNextVsync() override {
+ mRenderThread->queue().postDelayed(16_ms, [this]() {
+ mRenderThread->drainDisplayEventQueue();
+ });
+ }
+
+ virtual nsecs_t latestVsyncEvent() override {
+ return systemTime(CLOCK_MONOTONIC);
}
-}
-class DispatchFrameCallbacks : public RenderTask {
private:
RenderThread* mRenderThread;
-public:
- explicit DispatchFrameCallbacks(RenderThread* rt) : mRenderThread(rt) {}
-
- virtual void run() override {
- mRenderThread->dispatchFrameCallbacks();
- }
};
-static bool gHasRenderThreadInstance = false;
-
bool RenderThread::hasInstance() {
return gHasRenderThreadInstance;
}
+void RenderThread::setOnStartHook(void (*onStartHook)()) {
+ LOG_ALWAYS_FATAL_IF(hasInstance(), "can't set an onStartHook after we've started...");
+ gOnStartHook = onStartHook;
+}
+
RenderThread& RenderThread::getInstance() {
// This is a pointer because otherwise __cxa_finalize
// will try to delete it like a Good Citizen but that causes us to crash
@@ -159,19 +124,16 @@ RenderThread& RenderThread::getInstance() {
return *sInstance;
}
-RenderThread::RenderThread() : Thread(true)
- , mNextWakeup(LLONG_MAX)
- , mDisplayEventReceiver(nullptr)
+RenderThread::RenderThread()
+ : ThreadBase()
+ , mVsyncSource(nullptr)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
- , mFrameCallbackTask(nullptr)
, mRenderState(nullptr)
, mEglManager(nullptr)
, mVkManager(nullptr) {
Properties::load();
- mFrameCallbackTask = new DispatchFrameCallbacks(this);
- mLooper = new Looper(false);
- run("RenderThread");
+ start("RenderThread");
}
RenderThread::~RenderThread() {
@@ -179,22 +141,27 @@ RenderThread::~RenderThread() {
}
void RenderThread::initializeDisplayEventReceiver() {
- LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
- mDisplayEventReceiver = new DisplayEventReceiver();
- status_t status = mDisplayEventReceiver->initCheck();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver "
- "failed with status: %d", status);
-
- // Register the FD
- mLooper->addFd(mDisplayEventReceiver->getFd(), 0,
- Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
+ LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second DisplayEventReceiver?");
+
+ if (!Properties::isolatedProcess) {
+ auto receiver = std::make_unique<DisplayEventReceiver>();
+ status_t status = receiver->initCheck();
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
+ "Initialization of DisplayEventReceiver "
+ "failed with status: %d",
+ status);
+
+ // Register the FD
+ mLooper->addFd(receiver->getFd(), 0, Looper::EVENT_INPUT,
+ RenderThread::displayEventReceiverCallback, this);
+ mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver));
+ } else {
+ mVsyncSource = new DummyVsyncSource(this);
+ }
}
void RenderThread::initThreadLocals() {
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
- LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
+ mDisplayInfo = DeviceInfo::queryDisplayInfo();
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
mTimeLord.setFrameInterval(frameIntervalNanos);
initializeDisplayEventReceiver();
@@ -232,7 +199,7 @@ void RenderThread::dumpGraphicsMemory(int fd) {
break;
}
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
@@ -241,7 +208,6 @@ void RenderThread::dumpGraphicsMemory(int fd) {
}
Readback& RenderThread::readback() {
-
if (!mReadback) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
@@ -249,14 +215,13 @@ Readback& RenderThread::readback() {
mReadback = new OpenGLReadbackImpl(*this);
break;
case RenderPipelineType::SkiaGL:
- case RenderPipelineType::SkiaVulkan:
- // It works to use the OpenGL pipeline for Vulkan but this is not
- // ideal as it causes us to create an OpenGL context in addition
- // to the Vulkan one.
mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
break;
+ case RenderPipelineType::SkiaVulkan:
+ mReadback = new skiapipeline::SkiaVulkanReadback(*this);
+ break;
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
@@ -264,62 +229,44 @@ Readback& RenderThread::readback() {
return *mReadback;
}
-void RenderThread::setGrContext(GrContext* context) {
+void RenderThread::setGrContext(sk_sp<GrContext> context) {
mCacheManager->reset(context);
- if (mGrContext.get()) {
+ if (mGrContext) {
mGrContext->releaseResourcesAndAbandonContext();
}
- mGrContext.reset(context);
+ mGrContext = std::move(context);
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
ALOGE("Display event receiver pipe was closed or an error occurred. "
- "events=0x%x", events);
- return 0; // remove the callback
+ "events=0x%x",
+ events);
+ return 0; // remove the callback
}
if (!(events & Looper::EVENT_INPUT)) {
ALOGW("Received spurious callback for unhandled poll event. "
- "events=0x%x", events);
- return 1; // keep the callback
+ "events=0x%x",
+ events);
+ return 1; // keep the callback
}
reinterpret_cast<RenderThread*>(data)->drainDisplayEventQueue();
- return 1; // keep the callback
-}
-
-static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) {
- DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
- nsecs_t latest = 0;
- ssize_t n;
- while ((n = receiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
- for (ssize_t i = 0; i < n; i++) {
- const DisplayEventReceiver::Event& ev = buf[i];
- switch (ev.header.type) {
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
- latest = ev.header.timestamp;
- break;
- }
- }
- }
- if (n < 0) {
- ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
- }
- return latest;
+ return 1; // keep the callback
}
void RenderThread::drainDisplayEventQueue() {
ATRACE_CALL();
- nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
+ nsecs_t vsyncEvent = mVsyncSource->latestVsyncEvent();
if (vsyncEvent > 0) {
mVsyncRequested = false;
if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
ATRACE_NAME("queue mFrameCallbackTask");
mFrameCallbackTaskPending = true;
nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY);
- queueAt(mFrameCallbackTask, runAt);
+ queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); });
}
}
}
@@ -335,7 +282,8 @@ void RenderThread::dispatchFrameCallbacks() {
// Assume one of them will probably animate again so preemptively
// request the next vsync in case it occurs mid-frame
requestVsync();
- for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) {
+ for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end();
+ it++) {
(*it)->doFrame();
}
}
@@ -344,50 +292,25 @@ void RenderThread::dispatchFrameCallbacks() {
void RenderThread::requestVsync() {
if (!mVsyncRequested) {
mVsyncRequested = true;
- status_t status = mDisplayEventReceiver->requestNextVsync();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
- "requestNextVsync failed with status: %d", status);
+ mVsyncSource->requestNextVsync();
}
}
bool RenderThread::threadLoop() {
setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
+ if (gOnStartHook) {
+ gOnStartHook();
+ }
initThreadLocals();
- int timeoutMillis = -1;
- for (;;) {
- int result = mLooper->pollOnce(timeoutMillis);
- LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR,
- "RenderThread Looper POLL_ERROR!");
-
- nsecs_t nextWakeup;
- {
- FatVector<RenderTask*, 10> workQueue;
- // Process our queue, if we have anything. By first acquiring
- // all the pending events then processing them we avoid vsync
- // starvation if more tasks are queued while we are processing tasks.
- while (RenderTask* task = nextTask(&nextWakeup)) {
- workQueue.push_back(task);
- }
- for (auto task : workQueue) {
- task->run();
- // task may have deleted itself, do not reference it again
- }
- }
- if (nextWakeup == LLONG_MAX) {
- timeoutMillis = -1;
- } else {
- nsecs_t timeoutNanos = nextWakeup - systemTime(SYSTEM_TIME_MONOTONIC);
- timeoutMillis = nanoseconds_to_milliseconds(timeoutNanos);
- if (timeoutMillis < 0) {
- timeoutMillis = 0;
- }
- }
+ while (true) {
+ waitForWork();
+ processQueue();
if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
drainDisplayEventQueue();
- mFrameCallbacks.insert(
- mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end());
+ mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
+ mPendingRegistrationFrameCallbacks.end());
mPendingRegistrationFrameCallbacks.clear();
requestVsync();
}
@@ -404,46 +327,6 @@ bool RenderThread::threadLoop() {
return false;
}
-void RenderThread::queue(RenderTask* task) {
- AutoMutex _lock(mLock);
- mQueue.queue(task);
- if (mNextWakeup && task->mRunAt < mNextWakeup) {
- mNextWakeup = 0;
- mLooper->wake();
- }
-}
-
-void RenderThread::queueAndWait(RenderTask* task) {
- // These need to be local to the thread to avoid the Condition
- // signaling the wrong thread. The easiest way to achieve that is to just
- // make this on the stack, although that has a slight cost to it
- Mutex mutex;
- Condition condition;
- SignalingRenderTask syncTask(task, &mutex, &condition);
-
- AutoMutex _lock(mutex);
- queue(&syncTask);
- while (!syncTask.hasRun()) {
- condition.wait(mutex);
- }
-}
-
-void RenderThread::queueAtFront(RenderTask* task) {
- AutoMutex _lock(mLock);
- mQueue.queueAtFront(task);
- mLooper->wake();
-}
-
-void RenderThread::queueAt(RenderTask* task, nsecs_t runAtNs) {
- task->mRunAt = runAtNs;
- queue(task);
-}
-
-void RenderThread::remove(RenderTask* task) {
- AutoMutex _lock(mLock);
- mQueue.remove(task);
-}
-
void RenderThread::postFrameCallback(IFrameCallback* callback) {
mPendingRegistrationFrameCallbacks.insert(callback);
}
@@ -461,26 +344,6 @@ void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
}
}
-RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
- AutoMutex _lock(mLock);
- RenderTask* next = mQueue.peek();
- if (!next) {
- mNextWakeup = LLONG_MAX;
- } else {
- mNextWakeup = next->mRunAt;
- // Most tasks won't be delayed, so avoid unnecessary systemTime() calls
- if (next->mRunAt <= 0 || next->mRunAt <= systemTime(SYSTEM_TIME_MONOTONIC)) {
- next = mQueue.next();
- } else {
- next = nullptr;
- }
- }
- if (nextWakeup) {
- *nextWakeup = mNextWakeup;
- }
- return next;
-}
-
sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
@@ -491,12 +354,16 @@ sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
case RenderPipelineType::SkiaVulkan:
return skiapipeline::SkiaVulkanPipeline::allocateHardwareBitmap(*this, skBitmap);
default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
return nullptr;
}
+bool RenderThread::isCurrent() {
+ return gettid() == getInstance().getTid();
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index bef47b3e27c5..689f518bad1b 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -22,21 +22,23 @@
#include "../JankTracker.h"
#include "CacheManager.h"
#include "TimeLord.h"
+#include "thread/ThreadBase.h"
#include <GrContext.h>
-#include <cutils/compiler.h>
#include <SkBitmap.h>
+#include <cutils/compiler.h>
#include <ui/DisplayInfo.h>
#include <utils/Looper.h>
#include <utils/Thread.h>
+#include <thread/ThreadBase.h>
#include <memory>
+#include <mutex>
#include <set>
namespace android {
class Bitmap;
-class DisplayEventReceiver;
namespace uirenderer {
@@ -47,26 +49,10 @@ class TestUtils;
namespace renderthread {
class CanvasContext;
-class DispatchFrameCallbacks;
class EglManager;
class RenderProxy;
class VulkanManager;
-class TaskQueue {
-public:
- TaskQueue();
-
- RenderTask* next();
- void queue(RenderTask* task);
- void queueAtFront(RenderTask* task);
- RenderTask* peek();
- void remove(RenderTask* task);
-
-private:
- RenderTask* mHead;
- RenderTask* mTail;
-};
-
// Mimics android.view.Choreographer.FrameCallback
class IFrameCallback {
public:
@@ -76,16 +62,22 @@ protected:
~IFrameCallback() {}
};
-class ANDROID_API RenderThread : public Thread {
+struct VsyncSource {
+ virtual void requestNextVsync() = 0;
+ virtual nsecs_t latestVsyncEvent() = 0;
+ virtual ~VsyncSource() {}
+};
+
+class DummyVsyncSource;
+
+class RenderThread : private ThreadBase {
PREVENT_COPY_AND_ASSIGN(RenderThread);
+
public:
- // RenderThread takes complete ownership of tasks that are queued
- // and will delete them after they are run
- ANDROID_API void queue(RenderTask* task);
- ANDROID_API void queueAndWait(RenderTask* task);
- ANDROID_API void queueAtFront(RenderTask* task);
- void queueAt(RenderTask* task, nsecs_t runAtNs);
- void remove(RenderTask* task);
+ // Sets a callback that fires before any RenderThread setup has occured.
+ ANDROID_API static void setOnStartHook(void (*onStartHook)());
+
+ WorkQueue& queue() { return ThreadBase::queue(); }
// Mimics android.view.Choreographer
void postFrameCallback(IFrameCallback* callback);
@@ -103,7 +95,7 @@ public:
const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; }
GrContext* getGrContext() const { return mGrContext.get(); }
- void setGrContext(GrContext* cxt);
+ void setGrContext(sk_sp<GrContext> cxt);
CacheManager& cacheManager() { return *mCacheManager; }
VulkanManager& vulkanManager() { return *mVkManager; }
@@ -111,12 +103,21 @@ public:
sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& skBitmap);
void dumpGraphicsMemory(int fd);
+ /**
+ * isCurrent provides a way to query, if the caller is running on
+ * the render thread.
+ *
+ * @return true only if isCurrent is invoked from the render thread.
+ */
+ static bool isCurrent();
+
protected:
virtual bool threadLoop() override;
private:
friend class DispatchFrameCallbacks;
friend class RenderProxy;
+ friend class DummyVsyncSource;
friend class android::uirenderer::TestUtils;
RenderThread();
@@ -132,20 +133,9 @@ private:
void dispatchFrameCallbacks();
void requestVsync();
- // Returns the next task to be run. If this returns NULL nextWakeup is set
- // to the time to requery for the nextTask to run. mNextWakeup is also
- // set to this time
- RenderTask* nextTask(nsecs_t* nextWakeup);
-
- sp<Looper> mLooper;
- Mutex mLock;
-
- nsecs_t mNextWakeup;
- TaskQueue mQueue;
-
DisplayInfo mDisplayInfo;
- DisplayEventReceiver* mDisplayEventReceiver;
+ VsyncSource* mVsyncSource;
bool mVsyncRequested;
std::set<IFrameCallback*> mFrameCallbacks;
// We defer the actual registration of these callbacks until
@@ -154,7 +144,6 @@ private:
// the previous one
std::set<IFrameCallback*> mPendingRegistrationFrameCallbacks;
bool mFrameCallbackTaskPending;
- DispatchFrameCallbacks* mFrameCallbackTask;
TimeLord mTimeLord;
RenderState* mRenderState;
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index 6c2575f699bb..b82c5d159756 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -19,10 +19,7 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-TimeLord::TimeLord()
- : mFrameIntervalNanos(milliseconds_to_nanoseconds(16))
- , mFrameTimeNanos(0) {
-}
+TimeLord::TimeLord() : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)), mFrameTimeNanos(0) {}
bool TimeLord::vsyncReceived(nsecs_t vsync) {
if (vsync > mFrameTimeNanos) {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 2195143658d2..21c91a26745b 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -31,11 +31,10 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-#define GET_PROC(F) m ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
-#define GET_DEV_PROC(F) m ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk" #F)
+#define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(instance, "vk" #F)
+#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(device, "vk" #F)
-VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {
-}
+VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {}
void VulkanManager::destroy() {
if (!hasVkContext()) return;
@@ -51,12 +50,15 @@ void VulkanManager::destroy() {
}
void VulkanManager::initialize() {
- if (hasVkContext()) { return; }
+ if (hasVkContext()) {
+ return;
+ }
auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
mBackendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr,
- &mPresentQueueIndex, canPresent));
+ &mPresentQueueIndex, canPresent));
+ LOG_ALWAYS_FATAL_IF(!mBackendContext.get());
// Get all the addresses of needed vulkan functions
VkInstance instance = mBackendContext->fInstance;
@@ -99,15 +101,19 @@ void VulkanManager::initialize() {
// this needs to be on the render queue
commandPoolInfo.queueFamilyIndex = mBackendContext->fGraphicsQueueIndex;
commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- SkDEBUGCODE(VkResult res =) mCreateCommandPool(mBackendContext->fDevice,
- &commandPoolInfo, nullptr, &mCommandPool);
+ SkDEBUGCODE(VkResult res =) mCreateCommandPool(mBackendContext->fDevice, &commandPoolInfo,
+ nullptr, &mCommandPool);
SkASSERT(VK_SUCCESS == res);
}
mGetDeviceQueue(mBackendContext->fDevice, mPresentQueueIndex, 0, &mPresentQueue);
- mRenderThread.setGrContext(GrContext::Create(kVulkan_GrBackend,
- (GrBackendContext) mBackendContext.get()));
+ GrContextOptions options;
+ options.fDisableDistanceFieldPaths = true;
+ mRenderThread.cacheManager().configureContext(&options);
+ sk_sp<GrContext> grContext(GrContext::MakeVulkan(mBackendContext, options));
+ LOG_ALWAYS_FATAL_IF(!grContext.get());
+ mRenderThread.setGrContext(grContext);
DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize());
if (Properties::enablePartialUpdates && Properties::useBufferAge) {
@@ -127,13 +133,13 @@ VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurfa
surface->mCurrentBackbufferIndex = 0;
}
- VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
- surface->mCurrentBackbufferIndex;
+ VulkanSurface::BackbufferInfo* backbuffer =
+ surface->mBackbuffers + surface->mCurrentBackbufferIndex;
// Before we reuse a backbuffer, make sure its fences have all signaled so that we can safely
// reuse its commands buffers.
- VkResult res = mWaitForFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences,
- true, UINT64_MAX);
+ VkResult res =
+ mWaitForFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences, true, UINT64_MAX);
if (res != VK_SUCCESS) {
return nullptr;
}
@@ -141,7 +147,6 @@ VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurfa
return backbuffer;
}
-
SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
SkASSERT(backbuffer);
@@ -154,7 +159,8 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
// The acquire will signal the attached mAcquireSemaphore. We use this to know the image has
// finished presenting and that it is safe to begin sending new commands to the returned image.
res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->mImageIndex);
+ backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
+ &backbuffer->mImageIndex);
if (VK_ERROR_SURFACE_LOST_KHR == res) {
// need to figure out how to create a new vkSurface without the platformData*
@@ -172,7 +178,8 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
// acquire the image
res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->mImageIndex);
+ backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
+ &backbuffer->mImageIndex);
if (VK_SUCCESS != res) {
return nullptr;
@@ -182,25 +189,25 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
// set up layout transfer from initial to color attachment
VkImageLayout layout = surface->mImageInfos[backbuffer->mImageIndex].mImageLayout;
SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
- VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout)
+ ? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
+ : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- 0 : VK_ACCESS_MEMORY_READ_BIT;
+ VkAccessFlags srcAccessMask =
+ (VK_IMAGE_LAYOUT_UNDEFINED == layout) ? 0 : VK_ACCESS_MEMORY_READ_BIT;
VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
- mPresentQueueIndex, // srcQueueFamilyIndex
- mBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ NULL, // pNext
+ srcAccessMask, // outputMask
+ dstAccessMask, // inputMask
+ layout, // oldLayout
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
+ mPresentQueueIndex, // srcQueueFamilyIndex
+ mBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex
+ surface->mImages[backbuffer->mImageIndex], // image
+ {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
};
mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[0], 0);
@@ -210,8 +217,8 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
info.flags = 0;
mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[0], &info);
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0,
- 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
+ mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0, 0,
+ nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[0]);
@@ -235,7 +242,7 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
GrVkImageInfo* imageInfo;
sk_sp<SkSurface> skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface;
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
- SkSurface::kFlushRead_BackendHandleAccess);
+ SkSurface::kFlushRead_BackendHandleAccess);
imageInfo->updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
surface->mBackbuffer = std::move(skSurface);
@@ -246,14 +253,14 @@ void VulkanManager::destroyBuffers(VulkanSurface* surface) {
if (surface->mBackbuffers) {
for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
mWaitForFences(mBackendContext->fDevice, 2, surface->mBackbuffers[i].mUsageFences, true,
- UINT64_MAX);
+ UINT64_MAX);
surface->mBackbuffers[i].mImageIndex = -1;
mDestroySemaphore(mBackendContext->fDevice, surface->mBackbuffers[i].mAcquireSemaphore,
- nullptr);
+ nullptr);
mDestroySemaphore(mBackendContext->fDevice, surface->mBackbuffers[i].mRenderSemaphore,
- nullptr);
+ nullptr);
mFreeCommandBuffers(mBackendContext->fDevice, mCommandPool, 2,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
+ surface->mBackbuffers[i].mTransitionCmdBuffers);
mDestroyFence(mBackendContext->fDevice, surface->mBackbuffers[i].mUsageFences[0], 0);
mDestroyFence(mBackendContext->fDevice, surface->mBackbuffers[i].mUsageFences[1], 0);
}
@@ -290,11 +297,11 @@ void VulkanManager::destroySurface(VulkanSurface* surface) {
void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExtent2D extent) {
mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain, &surface->mImageCount,
- nullptr);
+ nullptr);
SkASSERT(surface->mImageCount);
surface->mImages = new VkImage[surface->mImageCount];
- mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain,
- &surface->mImageCount, surface->mImages);
+ mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain, &surface->mImageCount,
+ surface->mImages);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
@@ -303,7 +310,7 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
for (uint32_t i = 0; i < surface->mImageCount; ++i) {
GrVkImageInfo info;
info.fImage = surface->mImages[i];
- info.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
+ info.fAlloc = GrVkAlloc();
info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
info.fFormat = format;
@@ -312,8 +319,8 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
GrBackendRenderTarget backendRT(extent.width, extent.height, 0, 0, info);
VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
- imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(),
- backendRT, kTopLeft_GrSurfaceOrigin, nullptr, &props);
+ imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
+ mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin, nullptr, &props);
}
SkASSERT(mCommandPool != VK_NULL_HANDLE);
@@ -343,16 +350,16 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
SkDEBUGCODE(VkResult res);
surface->mBackbuffers[i].mImageIndex = -1;
- SkDEBUGCODE(res = ) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mAcquireSemaphore);
- SkDEBUGCODE(res = ) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mRenderSemaphore);
- SkDEBUGCODE(res = ) mAllocateCommandBuffers(mBackendContext->fDevice, &commandBuffersInfo,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
- SkDEBUGCODE(res = ) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[0]);
- SkDEBUGCODE(res = ) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[1]);
+ SkDEBUGCODE(res =) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
+ &surface->mBackbuffers[i].mAcquireSemaphore);
+ SkDEBUGCODE(res =) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
+ &surface->mBackbuffers[i].mRenderSemaphore);
+ SkDEBUGCODE(res =) mAllocateCommandBuffers(mBackendContext->fDevice, &commandBuffersInfo,
+ surface->mBackbuffers[i].mTransitionCmdBuffers);
+ SkDEBUGCODE(res =) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
+ &surface->mBackbuffers[i].mUsageFences[0]);
+ SkDEBUGCODE(res =) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
+ &surface->mBackbuffers[i].mUsageFences[1]);
SkASSERT(VK_SUCCESS == res);
}
surface->mCurrentBackbufferIndex = surface->mImageCount;
@@ -362,35 +369,36 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
// check for capabilities
VkSurfaceCapabilitiesKHR caps;
VkResult res = mGetPhysicalDeviceSurfaceCapabilitiesKHR(mBackendContext->fPhysicalDevice,
- surface->mVkSurface, &caps);
+ surface->mVkSurface, &caps);
if (VK_SUCCESS != res) {
return false;
}
uint32_t surfaceFormatCount;
res = mGetPhysicalDeviceSurfaceFormatsKHR(mBackendContext->fPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, nullptr);
+ &surfaceFormatCount, nullptr);
if (VK_SUCCESS != res) {
return false;
}
FatVector<VkSurfaceFormatKHR, 4> surfaceFormats(surfaceFormatCount);
res = mGetPhysicalDeviceSurfaceFormatsKHR(mBackendContext->fPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, surfaceFormats.data());
+ &surfaceFormatCount, surfaceFormats.data());
if (VK_SUCCESS != res) {
return false;
}
uint32_t presentModeCount;
res = mGetPhysicalDeviceSurfacePresentModesKHR(mBackendContext->fPhysicalDevice,
- surface->mVkSurface, &presentModeCount, nullptr);
+ surface->mVkSurface, &presentModeCount, nullptr);
if (VK_SUCCESS != res) {
return false;
}
FatVector<VkPresentModeKHR, VK_PRESENT_MODE_RANGE_SIZE_KHR> presentModes(presentModeCount);
res = mGetPhysicalDeviceSurfacePresentModesKHR(mBackendContext->fPhysicalDevice,
- surface->mVkSurface, &presentModeCount, presentModes.data());
+ surface->mVkSurface, &presentModeCount,
+ presentModes.data());
if (VK_SUCCESS != res) {
return false;
}
@@ -420,12 +428,12 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
SkASSERT(caps.supportedTransforms & caps.currentTransform);
- SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
+ SkASSERT(caps.supportedCompositeAlpha &
+ (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
VkCompositeAlphaFlagBitsKHR composite_alpha =
- (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
+ ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
+ : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
// Pick our surface format. For now, just make sure it matches our sRGB request:
VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
@@ -470,7 +478,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
swapchainCreateInfo.imageArrayLayers = 1;
swapchainCreateInfo.imageUsage = usageFlags;
- uint32_t queueFamilies[] = { mBackendContext->fGraphicsQueueIndex, mPresentQueueIndex };
+ uint32_t queueFamilies[] = {mBackendContext->fGraphicsQueueIndex, mPresentQueueIndex};
if (mBackendContext->fGraphicsQueueIndex != mPresentQueueIndex) {
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
swapchainCreateInfo.queueFamilyIndexCount = 2;
@@ -488,7 +496,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
swapchainCreateInfo.oldSwapchain = surface->mSwapchain;
res = mCreateSwapchainKHR(mBackendContext->fDevice, &swapchainCreateInfo, nullptr,
- &surface->mSwapchain);
+ &surface->mSwapchain);
if (VK_SUCCESS != res) {
return false;
}
@@ -507,7 +515,6 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
return true;
}
-
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window) {
initialize();
@@ -524,21 +531,20 @@ VulkanSurface* VulkanManager::createSurface(ANativeWindow* window) {
surfaceCreateInfo.flags = 0;
surfaceCreateInfo.window = window;
- VkResult res = mCreateAndroidSurfaceKHR(mBackendContext->fInstance, &surfaceCreateInfo,
- nullptr, &surface->mVkSurface);
+ VkResult res = mCreateAndroidSurfaceKHR(mBackendContext->fInstance, &surfaceCreateInfo, nullptr,
+ &surface->mVkSurface);
if (VK_SUCCESS != res) {
delete surface;
return nullptr;
}
-SkDEBUGCODE(
- VkBool32 supported;
- res = mGetPhysicalDeviceSurfaceSupportKHR(mBackendContext->fPhysicalDevice,
- mPresentQueueIndex, surface->mVkSurface, &supported);
- // All physical devices and queue families on Android must be capable of presentation with any
- // native window.
- SkASSERT(VK_SUCCESS == res && supported);
-);
+ SkDEBUGCODE(VkBool32 supported; res = mGetPhysicalDeviceSurfaceSupportKHR(
+ mBackendContext->fPhysicalDevice, mPresentQueueIndex,
+ surface->mVkSurface, &supported);
+ // All physical devices and queue families on Android must be capable of
+ // presentation with any
+ // native window.
+ SkASSERT(VK_SUCCESS == res && supported););
if (!createSwapchain(surface)) {
destroySurface(surface);
@@ -573,11 +579,9 @@ static VkAccessFlags layoutToSrcAccessMask(const VkImageLayout layout) {
VkAccessFlags flags = 0;
if (VK_IMAGE_LAYOUT_GENERAL == layout) {
flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_TRANSFER_WRITE_BIT |
- VK_ACCESS_TRANSFER_READ_BIT |
- VK_ACCESS_SHADER_READ_BIT |
- VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT;
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT |
+ VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_HOST_WRITE_BIT |
+ VK_ACCESS_HOST_READ_BIT;
} else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
flags = VK_ACCESS_HOST_WRITE_BIT;
} else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
@@ -600,12 +604,13 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
mDeviceWaitIdle(mBackendContext->fDevice);
}
- VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
- surface->mCurrentBackbufferIndex;
+ SkASSERT(surface->mBackbuffers);
+ VulkanSurface::BackbufferInfo* backbuffer =
+ surface->mBackbuffers + surface->mCurrentBackbufferIndex;
GrVkImageInfo* imageInfo;
SkSurface* skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface.get();
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
- SkSurface::kFlushRead_BackendHandleAccess);
+ SkSurface::kFlushRead_BackendHandleAccess);
// Check to make sure we never change the actually wrapped image
SkASSERT(imageInfo->fImage == surface->mImages[backbuffer->mImageIndex]);
@@ -618,16 +623,16 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
VkAccessFlags dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
- mBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex
- mPresentQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ NULL, // pNext
+ srcAccessMask, // outputMask
+ dstAccessMask, // inputMask
+ layout, // oldLayout
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
+ mBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex
+ mPresentQueueIndex, // dstQueueFamilyIndex
+ surface->mImages[backbuffer->mImageIndex], // image
+ {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
};
mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[1], 0);
@@ -636,8 +641,8 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
info.flags = 0;
mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[1], &info);
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[1], srcStageMask, dstStageMask, 0,
- 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
+ mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[1], srcStageMask, dstStageMask, 0, 0,
+ nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[1]);
surface->mImageInfos[backbuffer->mImageIndex].mImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
@@ -661,16 +666,15 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
// Submit present operation to present queue. We use a semaphore here to make sure all rendering
// to the image is complete and that the layout has been change to present on the graphics
// queue.
- const VkPresentInfoKHR presentInfo =
- {
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
- NULL, // pNext
- 1, // waitSemaphoreCount
- &backbuffer->mRenderSemaphore, // pWaitSemaphores
- 1, // swapchainCount
- &surface->mSwapchain, // pSwapchains
- &backbuffer->mImageIndex, // pImageIndices
- NULL // pResults
+ const VkPresentInfoKHR presentInfo = {
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
+ NULL, // pNext
+ 1, // waitSemaphoreCount
+ &backbuffer->mRenderSemaphore, // pWaitSemaphores
+ 1, // swapchainCount
+ &surface->mSwapchain, // pSwapchains
+ &backbuffer->mImageIndex, // pImageIndices
+ NULL // pResults
};
mQueuePresentKHR(mPresentQueue, &presentInfo);
@@ -682,10 +686,11 @@ void VulkanManager::swapBuffers(VulkanSurface* surface) {
}
int VulkanManager::getAge(VulkanSurface* surface) {
- VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
- surface->mCurrentBackbufferIndex;
- if (mSwapBehavior == SwapBehavior::Discard
- || surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
+ SkASSERT(surface->mBackbuffers);
+ VulkanSurface::BackbufferInfo* backbuffer =
+ surface->mBackbuffers + surface->mCurrentBackbufferIndex;
+ if (mSwapBehavior == SwapBehavior::Discard ||
+ surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
return 0;
}
uint16_t lastUsed = surface->mImageInfos[backbuffer->mImageIndex].mLastUsed;
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index d225b3fc4ec0..c319c9ec209f 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -37,13 +37,14 @@ public:
private:
friend class VulkanManager;
struct BackbufferInfo {
- uint32_t mImageIndex; // image this is associated with
- VkSemaphore mAcquireSemaphore; // we signal on this for acquisition of image
- VkSemaphore mRenderSemaphore; // we wait on this for rendering to be done
- VkCommandBuffer mTransitionCmdBuffers[2]; // to transition layout between present and render
+ uint32_t mImageIndex; // image this is associated with
+ VkSemaphore mAcquireSemaphore; // we signal on this for acquisition of image
+ VkSemaphore mRenderSemaphore; // we wait on this for rendering to be done
+ VkCommandBuffer
+ mTransitionCmdBuffers[2]; // to transition layout between present and render
// We use these fences to make sure the above Command buffers have finished their work
// before attempting to reuse them or destroy them.
- VkFence mUsageFences[2];
+ VkFence mUsageFences[2];
};
struct ImageInfo {
@@ -58,11 +59,11 @@ private:
VkSurfaceKHR mVkSurface = VK_NULL_HANDLE;
VkSwapchainKHR mSwapchain = VK_NULL_HANDLE;
- BackbufferInfo* mBackbuffers;
+ BackbufferInfo* mBackbuffers = nullptr;
uint32_t mCurrentBackbufferIndex;
uint32_t mImageCount;
- VkImage* mImages;
+ VkImage* mImages = nullptr;
ImageInfo* mImageInfos;
uint16_t mCurrentTime = 0;
};
@@ -118,11 +119,16 @@ private:
VulkanSurface::BackbufferInfo* getAvailableBackbuffer(VulkanSurface* surface);
// simple wrapper class that exists only to initialize a pointer to NULL
- template <typename FNPTR_TYPE> class VkPtr {
+ template <typename FNPTR_TYPE>
+ class VkPtr {
public:
VkPtr() : fPtr(NULL) {}
- VkPtr operator=(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }
+ VkPtr operator=(FNPTR_TYPE ptr) {
+ fPtr = ptr;
+ return *this;
+ }
operator FNPTR_TYPE() const { return fPtr; }
+
private:
FNPTR_TYPE fPtr;
};
@@ -183,4 +189,3 @@ private:
} /* namespace android */
#endif /* VULKANMANAGER_H */
-
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 32b5132a6fa3..3d50d2d7e59c 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -17,18 +17,18 @@
#include "GraphicsStatsService.h"
#include "JankTracker.h"
+#include "protos/graphicsstats.pb.h"
-#include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <log/log.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-#include <sys/mman.h>
namespace android {
namespace uirenderer {
@@ -41,10 +41,10 @@ static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong"
constexpr int sHistogramSize = ProfileData::HistogramSize();
-static bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
- const std::string& package, int versionCode, int64_t startTime, int64_t endTime,
- const ProfileData* data);
-static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
+static bool mergeProfileDataIntoProto(protos::GraphicsStatsProto* proto,
+ const std::string& package, int64_t versionCode,
+ int64_t startTime, int64_t endTime, const ProfileData* data);
+static void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int outFd);
class FileDescriptor {
public:
@@ -57,6 +57,7 @@ public:
}
bool valid() { return mFd != -1; }
operator int() { return mFd; }
+
private:
int mFd;
};
@@ -68,21 +69,13 @@ public:
int GetErrno() { return mCopyAdapter.mErrno; }
- virtual bool Next(void** data, int* size) override {
- return mImpl.Next(data, size);
- }
+ virtual bool Next(void** data, int* size) override { return mImpl.Next(data, size); }
- virtual void BackUp(int count) override {
- mImpl.BackUp(count);
- }
+ virtual void BackUp(int count) override { mImpl.BackUp(count); }
- virtual int64 ByteCount() const override {
- return mImpl.ByteCount();
- }
+ virtual int64 ByteCount() const override { return mImpl.ByteCount(); }
- bool Flush() {
- return mImpl.Flush();
- }
+ bool Flush() { return mImpl.Flush(); }
private:
struct FDAdapter : public io::CopyingOutputStream {
@@ -95,7 +88,7 @@ private:
virtual bool Write(const void* buffer, int size) override {
int ret;
while (size) {
- ret = TEMP_FAILURE_RETRY( write(mFd, buffer, size) );
+ ret = TEMP_FAILURE_RETRY(write(mFd, buffer, size));
if (ret <= 0) {
mErrno = errno;
return false;
@@ -110,8 +103,8 @@ private:
io::CopyingOutputStreamAdaptor mImpl;
};
-bool GraphicsStatsService::parseFromFile(const std::string& path, service::GraphicsStatsProto* output) {
-
+bool GraphicsStatsService::parseFromFile(const std::string& path,
+ protos::GraphicsStatsProto* output) {
FileDescriptor fd{open(path.c_str(), O_RDONLY)};
if (!fd.valid()) {
int err = errno;
@@ -129,7 +122,7 @@ bool GraphicsStatsService::parseFromFile(const std::string& path, service::Graph
// we get an unexpected error
if (err != ENOENT) {
ALOGW("Failed to fstat '%s', errno=%d (%s) (st_size %d)", path.c_str(), err,
- strerror(err), (int) sb.st_size);
+ strerror(err), (int)sb.st_size);
}
return false;
}
@@ -154,14 +147,15 @@ bool GraphicsStatsService::parseFromFile(const std::string& path, service::Graph
io::ArrayInputStream input{data, dataSize};
bool success = output->ParseFromZeroCopyStream(&input);
if (!success) {
- ALOGW("Parse failed on '%s' error='%s'",
- path.c_str(), output->InitializationErrorString().c_str());
+ ALOGW("Parse failed on '%s' error='%s'", path.c_str(),
+ output->InitializationErrorString().c_str());
}
return success;
}
-bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
- int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
+bool mergeProfileDataIntoProto(protos::GraphicsStatsProto* proto, const std::string& package,
+ int64_t versionCode, int64_t startTime, int64_t endTime,
+ const ProfileData* data) {
if (proto->stats_start() == 0 || proto->stats_start() > startTime) {
proto->set_stats_start(startTime);
}
@@ -173,24 +167,25 @@ bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st
auto summary = proto->mutable_summary();
summary->set_total_frames(summary->total_frames() + data->totalFrameCount());
summary->set_janky_frames(summary->janky_frames() + data->jankFrameCount());
- summary->set_missed_vsync_count(
- summary->missed_vsync_count() + data->jankTypeCount(kMissedVsync));
- summary->set_high_input_latency_count(
- summary->high_input_latency_count() + data->jankTypeCount(kHighInputLatency));
- summary->set_slow_ui_thread_count(
- summary->slow_ui_thread_count() + data->jankTypeCount(kSlowUI));
- summary->set_slow_bitmap_upload_count(
- summary->slow_bitmap_upload_count() + data->jankTypeCount(kSlowSync));
- summary->set_slow_draw_count(
- summary->slow_draw_count() + data->jankTypeCount(kSlowRT));
+ summary->set_missed_vsync_count(summary->missed_vsync_count() +
+ data->jankTypeCount(kMissedVsync));
+ summary->set_high_input_latency_count(summary->high_input_latency_count() +
+ data->jankTypeCount(kHighInputLatency));
+ summary->set_slow_ui_thread_count(summary->slow_ui_thread_count() +
+ data->jankTypeCount(kSlowUI));
+ summary->set_slow_bitmap_upload_count(summary->slow_bitmap_upload_count() +
+ data->jankTypeCount(kSlowSync));
+ summary->set_slow_draw_count(summary->slow_draw_count() + data->jankTypeCount(kSlowRT));
+ summary->set_missed_deadline_count(summary->missed_deadline_count()
+ + data->jankTypeCount(kMissedDeadline));
bool creatingHistogram = false;
if (proto->histogram_size() == 0) {
proto->mutable_histogram()->Reserve(sHistogramSize);
creatingHistogram = true;
} else if (proto->histogram_size() != sHistogramSize) {
- ALOGE("Histogram size mismatch, proto is %d expected %d",
- proto->histogram_size(), sHistogramSize);
+ ALOGE("Histogram size mismatch, proto is %d expected %d", proto->histogram_size(),
+ sHistogramSize);
return false;
}
int index = 0;
@@ -198,14 +193,15 @@ bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st
data->histogramForEach([&](ProfileData::HistogramEntry entry) {
if (hitMergeError) return;
- service::GraphicsStatsHistogramBucketProto* bucket;
+ protos::GraphicsStatsHistogramBucketProto* bucket;
if (creatingHistogram) {
bucket = proto->add_histogram();
bucket->set_render_millis(entry.renderTimeMs);
} else {
bucket = proto->mutable_histogram(index);
if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) {
- ALOGW("Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
+ ALOGW("Frame time mistmatch %d vs. %u", bucket->render_millis(),
+ entry.renderTimeMs);
hitMergeError = true;
return;
}
@@ -216,7 +212,7 @@ bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st
return !hitMergeError;
}
-static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) {
+static int32_t findPercentile(protos::GraphicsStatsProto* proto, int percentile) {
int32_t pos = percentile * proto->summary().total_frames() / 100;
int32_t remaining = proto->summary().total_frames() - pos;
for (auto it = proto->histogram().rbegin(); it != proto->histogram().rend(); ++it) {
@@ -228,21 +224,21 @@ static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile
return 0;
}
-void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
+void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int fd) {
// This isn't a full validation, just enough that we can deref at will
if (proto->package_name().empty() || !proto->has_summary()) {
ALOGW("Skipping dump, invalid package_name() '%s' or summary %d",
- proto->package_name().c_str(), proto->has_summary());
+ proto->package_name().c_str(), proto->has_summary());
return;
}
dprintf(fd, "\nPackage: %s", proto->package_name().c_str());
- dprintf(fd, "\nVersion: %d", proto->version_code());
+ dprintf(fd, "\nVersion: %lld", proto->version_code());
dprintf(fd, "\nStats since: %lldns", proto->stats_start());
dprintf(fd, "\nStats end: %lldns", proto->stats_end());
auto summary = proto->summary();
dprintf(fd, "\nTotal frames rendered: %d", summary.total_frames());
dprintf(fd, "\nJanky frames: %d (%.2f%%)", summary.janky_frames(),
- (float) summary.janky_frames() / (float) summary.total_frames() * 100.0f);
+ (float)summary.janky_frames() / (float)summary.total_frames() * 100.0f);
dprintf(fd, "\n50th percentile: %dms", findPercentile(proto, 50));
dprintf(fd, "\n90th percentile: %dms", findPercentile(proto, 90));
dprintf(fd, "\n95th percentile: %dms", findPercentile(proto, 95));
@@ -252,6 +248,7 @@ void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
dprintf(fd, "\nNumber Slow UI thread: %d", summary.slow_ui_thread_count());
dprintf(fd, "\nNumber Slow bitmap uploads: %d", summary.slow_bitmap_upload_count());
dprintf(fd, "\nNumber Slow issue draw commands: %d", summary.slow_draw_count());
+ dprintf(fd, "\nNumber Frame deadline missed: %d", summary.missed_deadline_count());
dprintf(fd, "\nHISTOGRAM:");
for (const auto& it : proto->histogram()) {
dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
@@ -260,8 +257,9 @@ void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
}
void GraphicsStatsService::saveBuffer(const std::string& path, const std::string& package,
- int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
- service::GraphicsStatsProto statsProto;
+ int64_t versionCode, int64_t startTime, int64_t endTime,
+ const ProfileData* data) {
+ protos::GraphicsStatsProto statsProto;
if (!parseFromFile(path, &statsProto)) {
statsProto.Clear();
}
@@ -275,8 +273,8 @@ void GraphicsStatsService::saveBuffer(const std::string& path, const std::string
return;
}
if (statsProto.package_name().empty() || !statsProto.has_summary()) {
- ALOGE("missing package_name() '%s' summary %d",
- statsProto.package_name().c_str(), statsProto.has_summary());
+ ALOGE("missing package_name() '%s' summary %d", statsProto.package_name().c_str(),
+ statsProto.has_summary());
return;
}
int outFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0660);
@@ -288,8 +286,8 @@ void GraphicsStatsService::saveBuffer(const std::string& path, const std::string
int wrote = write(outFd, &sCurrentFileVersion, sHeaderSize);
if (wrote != sHeaderSize) {
int err = errno;
- ALOGW("Failed to write header to '%s', returned=%d errno=%d (%s)",
- path.c_str(), wrote, err, strerror(err));
+ ALOGW("Failed to write header to '%s', returned=%d errno=%d (%s)", path.c_str(), wrote, err,
+ strerror(err));
close(outFd);
return;
}
@@ -297,8 +295,8 @@ void GraphicsStatsService::saveBuffer(const std::string& path, const std::string
FileOutputStreamLite output(outFd);
bool success = statsProto.SerializeToZeroCopyStream(&output) && output.Flush();
if (output.GetErrno() != 0) {
- ALOGW("Error writing to fd=%d, path='%s' err=%d (%s)",
- outFd, path.c_str(), output.GetErrno(), strerror(output.GetErrno()));
+ ALOGW("Error writing to fd=%d, path='%s' err=%d (%s)", outFd, path.c_str(),
+ output.GetErrno(), strerror(output.GetErrno()));
success = false;
} else if (!success) {
ALOGW("Serialize failed on '%s' unknown error", path.c_str());
@@ -312,30 +310,32 @@ public:
Dump(int outFd, DumpType type) : mFd(outFd), mType(type) {}
int fd() { return mFd; }
DumpType type() { return mType; }
- service::GraphicsStatsServiceDumpProto& proto() { return mProto; }
+ protos::GraphicsStatsServiceDumpProto& proto() { return mProto; }
+
private:
int mFd;
DumpType mType;
- service::GraphicsStatsServiceDumpProto mProto;
+ protos::GraphicsStatsServiceDumpProto mProto;
};
GraphicsStatsService::Dump* GraphicsStatsService::createDump(int outFd, DumpType type) {
return new Dump(outFd, type);
}
-void GraphicsStatsService::addToDump(Dump* dump, const std::string& path, const std::string& package,
- int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
- service::GraphicsStatsProto statsProto;
+void GraphicsStatsService::addToDump(Dump* dump, const std::string& path,
+ const std::string& package, int64_t versionCode,
+ int64_t startTime, int64_t endTime, const ProfileData* data) {
+ protos::GraphicsStatsProto statsProto;
if (!path.empty() && !parseFromFile(path, &statsProto)) {
statsProto.Clear();
}
- if (data && !mergeProfileDataIntoProto(
- &statsProto, package, versionCode, startTime, endTime, data)) {
+ if (data &&
+ !mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data)) {
return;
}
if (!statsProto.IsInitialized()) {
ALOGW("Failed to load profile data from path '%s' and data %p",
- path.empty() ? "<empty>" : path.c_str(), data);
+ path.empty() ? "<empty>" : path.c_str(), data);
return;
}
@@ -347,7 +347,7 @@ void GraphicsStatsService::addToDump(Dump* dump, const std::string& path, const
}
void GraphicsStatsService::addToDump(Dump* dump, const std::string& path) {
- service::GraphicsStatsProto statsProto;
+ protos::GraphicsStatsProto statsProto;
if (!parseFromFile(path, &statsProto)) {
return;
}
diff --git a/libs/hwui/service/GraphicsStatsService.h b/libs/hwui/service/GraphicsStatsService.h
index d0fd60ee1aba..389f599f439f 100644
--- a/libs/hwui/service/GraphicsStatsService.h
+++ b/libs/hwui/service/GraphicsStatsService.h
@@ -22,12 +22,11 @@
#include "utils/Macros.h"
namespace android {
-namespace service {
+namespace uirenderer {
+namespace protos {
class GraphicsStatsProto;
}
-namespace uirenderer {
-
/*
* The exported entry points used by GraphicsStatsService.java in f/b/services/core
*
@@ -44,17 +43,19 @@ public:
};
ANDROID_API static void saveBuffer(const std::string& path, const std::string& package,
- int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data);
+ int64_t versionCode, int64_t startTime, int64_t endTime,
+ const ProfileData* data);
ANDROID_API static Dump* createDump(int outFd, DumpType type);
- ANDROID_API static void addToDump(Dump* dump, const std::string& path, const std::string& package,
- int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data);
+ ANDROID_API static void addToDump(Dump* dump, const std::string& path,
+ const std::string& package, int64_t versionCode,
+ int64_t startTime, int64_t endTime, const ProfileData* data);
ANDROID_API static void addToDump(Dump* dump, const std::string& path);
ANDROID_API static void finishDump(Dump* dump);
// Visible for testing
- static bool parseFromFile(const std::string& path, service::GraphicsStatsProto* output);
+ static bool parseFromFile(const std::string& path, protos::GraphicsStatsProto* output);
};
} /* namespace uirenderer */
-} /* namespace android */ \ No newline at end of file
+} /* namespace android */
diff --git a/libs/hwui/tests/common/BitmapAllocationTestUtils.h b/libs/hwui/tests/common/BitmapAllocationTestUtils.h
index 2988979cc266..312b60bbc067 100644
--- a/libs/hwui/tests/common/BitmapAllocationTestUtils.h
+++ b/libs/hwui/tests/common/BitmapAllocationTestUtils.h
@@ -27,17 +27,17 @@ namespace test {
class BitmapAllocationTestUtils {
public:
- static sk_sp<Bitmap> allocateHeapBitmap(int width, int height,
- SkColorType colorType, std::function<void(SkBitmap& bitmap)> setup) {
- sk_sp<Bitmap> bitmap = TestUtils::createBitmap(width, height, colorType);
- SkBitmap skBitmap;
- bitmap->getSkBitmap(&skBitmap);
- setup(skBitmap);
- return bitmap;
+ static sk_sp<Bitmap> allocateHeapBitmap(int width, int height, SkColorType colorType,
+ std::function<void(SkBitmap& bitmap)> setup) {
+ sk_sp<Bitmap> bitmap = TestUtils::createBitmap(width, height, colorType);
+ SkBitmap skBitmap;
+ bitmap->getSkBitmap(&skBitmap);
+ setup(skBitmap);
+ return bitmap;
}
- static sk_sp<Bitmap> allocateHardwareBitmap(int width, int height,
- SkColorType colorType, std::function<void(SkBitmap& bitmap)> setup) {
+ static sk_sp<Bitmap> allocateHardwareBitmap(int width, int height, SkColorType colorType,
+ std::function<void(SkBitmap& bitmap)> setup) {
SkBitmap skBitmap;
SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType);
skBitmap.setInfo(info);
@@ -46,8 +46,8 @@ public:
return Bitmap::allocateHardwareBitmap(skBitmap);
}
- typedef sk_sp<Bitmap> (*BitmapAllocator) (int, int, SkColorType,
- std::function<void(SkBitmap& bitmap)> setup);
+ typedef sk_sp<Bitmap> (*BitmapAllocator)(int, int, SkColorType,
+ std::function<void(SkBitmap& bitmap)> setup);
template <class T, BitmapAllocator allocator>
static test::TestScene* createBitmapAllocationScene(const TestScene::Options&) {
@@ -55,22 +55,16 @@ public:
}
template <class BaseScene>
- static bool registerBitmapAllocationScene(std::string name, std::string description) {
- TestScene::registerScene({
- name + "GlTex",
- description + " (GlTex version).",
- createBitmapAllocationScene<BaseScene, &allocateHeapBitmap>
- });
+ static bool registerBitmapAllocationScene(std::string name, std::string description) {
+ TestScene::registerScene({name + "GlTex", description + " (GlTex version).",
+ createBitmapAllocationScene<BaseScene, &allocateHeapBitmap>});
- TestScene::registerScene({
- name + "EglImage",
- description + " (EglImage version).",
- createBitmapAllocationScene<BaseScene, &allocateHardwareBitmap>
- });
+ TestScene::registerScene({name + "EglImage", description + " (EglImage version).",
+ createBitmapAllocationScene<BaseScene, &allocateHardwareBitmap>});
return true;
}
};
-} // namespace test
-} // namespace uirenderer
-} // namespace android
+} // namespace test
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/common/LeakChecker.cpp b/libs/hwui/tests/common/LeakChecker.cpp
index fe38ec958527..5b361548eeda 100644
--- a/libs/hwui/tests/common/LeakChecker.cpp
+++ b/libs/hwui/tests/common/LeakChecker.cpp
@@ -19,10 +19,10 @@
#include "Caches.h"
#include "TestUtils.h"
-#include <cstdio>
-#include <iostream>
#include <memunreachable/memunreachable.h>
#include <unistd.h>
+#include <cstdio>
+#include <iostream>
#include <unordered_set>
using namespace std;
@@ -45,12 +45,12 @@ static void logUnreachable(initializer_list<UnreachableMemoryInfo> infolist) {
merged.allocation_bytes = max(merged.allocation_bytes, info.allocation_bytes);
merged.num_allocations = max(merged.num_allocations, info.num_allocations);
for (auto& leak : info.leaks) {
- if (addrs.find(leak.begin) == addrs.end()) {
- merged.leaks.push_back(leak);
- merged.num_leaks++;
- merged.leak_bytes += leak.size;
- addrs.insert(leak.begin);
- }
+ if (addrs.find(leak.begin) == addrs.end()) {
+ merged.leaks.push_back(leak);
+ merged.num_leaks++;
+ merged.leak_bytes += leak.size;
+ addrs.insert(leak.begin);
+ }
}
}
@@ -59,7 +59,7 @@ static void logUnreachable(initializer_list<UnreachableMemoryInfo> infolist) {
cout << endl << "Leaked memory!" << endl;
if (!merged.leaks[0].backtrace.num_frames) {
cout << "Re-run with 'export LIBC_DEBUG_MALLOC_OPTIONS=backtrace' to get backtraces"
- << endl;
+ << endl;
}
cout << merged.ToString(false);
}
diff --git a/libs/hwui/tests/common/LeakChecker.h b/libs/hwui/tests/common/LeakChecker.h
index cdf47d6bda80..e43df177cdba 100644
--- a/libs/hwui/tests/common/LeakChecker.h
+++ b/libs/hwui/tests/common/LeakChecker.h
@@ -22,7 +22,7 @@ namespace test {
class LeakChecker {
public:
static void checkForLeaks();
-}; // class TestUtils
+}; // class TestUtils
} /* namespace test */
} /* namespace uirenderer */
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index c1ca1e7ac28a..92b6cbdfc613 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -24,24 +24,23 @@ namespace test {
static const int IDENT_DISPLAYEVENT = 1;
-static android::DisplayInfo DUMMY_DISPLAY {
- 1080, //w
- 1920, //h
- 320.0, // xdpi
- 320.0, // ydpi
- 60.0, // fps
- 2.0, // density
- 0, // orientation
- false, // secure?
- 0, // appVsyncOffset
- 0, // presentationDeadline
+static android::DisplayInfo DUMMY_DISPLAY{
+ 1080, // w
+ 1920, // h
+ 320.0, // xdpi
+ 320.0, // ydpi
+ 60.0, // fps
+ 2.0, // density
+ 0, // orientation
+ false, // secure?
+ 0, // appVsyncOffset
+ 0, // presentationDeadline
};
DisplayInfo getBuiltInDisplay() {
#if !HWUI_NULL_GPU
DisplayInfo display;
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
+ sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &display);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
return display;
@@ -56,8 +55,8 @@ android::DisplayInfo gDisplay = DUMMY_DISPLAY;
TestContext::TestContext() {
mLooper = new Looper(true);
mSurfaceComposerClient = new SurfaceComposerClient();
- mLooper->addFd(mDisplayEventReceiver.getFd(), IDENT_DISPLAYEVENT,
- Looper::EVENT_INPUT, nullptr, nullptr);
+ mLooper->addFd(mDisplayEventReceiver.getFd(), IDENT_DISPLAYEVENT, Looper::EVENT_INPUT, nullptr,
+ nullptr);
}
TestContext::~TestContext() {}
@@ -78,13 +77,11 @@ void TestContext::createSurface() {
}
void TestContext::createWindowSurface() {
- mSurfaceControl = mSurfaceComposerClient->createSurface(String8("HwuiTest"),
- gDisplay.w, gDisplay.h, PIXEL_FORMAT_RGBX_8888);
+ mSurfaceControl = mSurfaceComposerClient->createSurface(String8("HwuiTest"), gDisplay.w,
+ gDisplay.h, PIXEL_FORMAT_RGBX_8888);
- SurfaceComposerClient::openGlobalTransaction();
- mSurfaceControl->setLayer(0x7FFFFFF);
- mSurfaceControl->show();
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction t;
+ t.setLayer(mSurfaceControl, 0x7FFFFFF).show(mSurfaceControl).apply();
mSurface = mSurfaceControl->getSurface();
}
@@ -124,10 +121,11 @@ void TestContext::waitForVsync() {
// Drain it
DisplayEventReceiver::Event buf[100];
- while (mDisplayEventReceiver.getEvents(buf, 100) > 0) { }
+ while (mDisplayEventReceiver.getEvents(buf, 100) > 0) {
+ }
#endif
}
-} // namespace test
-} // namespace uirenderer
-} // namespace android
+} // namespace test
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/common/TestContext.h b/libs/hwui/tests/common/TestContext.h
index 312988b968de..0996f4dc706e 100644
--- a/libs/hwui/tests/common/TestContext.h
+++ b/libs/hwui/tests/common/TestContext.h
@@ -17,24 +17,24 @@
#ifndef TESTCONTEXT_H
#define TESTCONTEXT_H
+#include <gui/BufferItemConsumer.h>
#include <gui/DisplayEventReceiver.h>
#include <gui/ISurfaceComposer.h>
-#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
-#include <gui/Surface.h>
#include <ui/DisplayInfo.h>
#include <utils/Looper.h>
-#include <thread>
#include <atomic>
+#include <thread>
namespace android {
namespace uirenderer {
namespace test {
extern DisplayInfo gDisplay;
-#define dp(x) ((x) * android::uirenderer::test::gDisplay.density)
+#define dp(x) ((x)*android::uirenderer::test::gDisplay.density)
DisplayInfo getBuiltInDisplay();
@@ -45,8 +45,7 @@ public:
// Must be called before surface();
void setRenderOffscreen(bool renderOffscreen) {
- LOG_ALWAYS_FATAL_IF(mSurface.get(),
- "Must be called before surface is created");
+ LOG_ALWAYS_FATAL_IF(mSurface.get(), "Must be called before surface is created");
mRenderOffscreen = renderOffscreen;
}
@@ -68,8 +67,8 @@ private:
bool mRenderOffscreen;
};
-} // namespace test
-} // namespace uirenderer
-} // namespace android
+} // namespace test
+} // namespace uirenderer
+} // namespace android
#endif
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.cpp b/libs/hwui/tests/common/TestListViewSceneBase.cpp
index 38c4848ebc41..fd331333d38a 100644
--- a/libs/hwui/tests/common/TestListViewSceneBase.cpp
+++ b/libs/hwui/tests/common/TestListViewSceneBase.cpp
@@ -35,17 +35,17 @@ void TestListViewSceneBase::createContent(int width, int height, Canvas& canvas)
for (int y = 0; y < height + (heightWithSpacing - 1); y += heightWithSpacing) {
int id = mListItems.size();
auto setup = std::bind(&TestListViewSceneBase::createListItem, this, std::placeholders::_1,
- std::placeholders::_2, id, mItemWidth, mItemHeight);
- auto node = TestUtils::createNode(mItemLeft, y, mItemLeft + mItemWidth,
- y + mItemHeight, setup);
+ std::placeholders::_2, id, mItemWidth, mItemHeight);
+ auto node =
+ TestUtils::createNode(mItemLeft, y, mItemLeft + mItemWidth, y + mItemHeight, setup);
mListItems.push_back(node);
}
mListView = TestUtils::createNode(0, 0, width, height,
- [this](RenderProperties& props, Canvas& canvas) {
- for (size_t ci = 0; ci < mListItems.size(); ci++) {
- canvas.drawRenderNode(mListItems[ci].get());
- }
- });
+ [this](RenderProperties& props, Canvas& canvas) {
+ for (size_t ci = 0; ci < mListItems.size(); ci++) {
+ canvas.drawRenderNode(mListItems[ci].get());
+ }
+ });
canvas.drawColor(Color::Grey_500, SkBlendMode::kSrcOver);
canvas.drawRenderNode(mListView.get());
@@ -56,8 +56,9 @@ void TestListViewSceneBase::doFrame(int frameNr) {
int itemIndexOffset = scrollPx / (mItemSpacing + mItemHeight);
int pxOffset = -(scrollPx % (mItemSpacing + mItemHeight));
- std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(mListView->stagingProperties().getWidth(),
- mListView->stagingProperties().getHeight()));
+ std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
+ mListView->stagingProperties().getWidth(), mListView->stagingProperties().getHeight(),
+ mListView.get()));
for (size_t ci = 0; ci < mListItems.size(); ci++) {
// update item position
auto listItem = mListItems[(ci + itemIndexOffset) % mListItems.size()];
@@ -72,6 +73,6 @@ void TestListViewSceneBase::doFrame(int frameNr) {
mListView->setStagingDisplayList(canvas->finishRecording());
}
-} // namespace test
-} // namespace uirenderer
-} // namespace android
+} // namespace test
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.h b/libs/hwui/tests/common/TestListViewSceneBase.h
index ed6867ab3750..ab0d3c74226b 100644
--- a/libs/hwui/tests/common/TestListViewSceneBase.h
+++ b/libs/hwui/tests/common/TestListViewSceneBase.h
@@ -15,9 +15,9 @@
*/
#pragma once
-#include "TestScene.h"
#include <RenderNode.h>
#include <RenderProperties.h>
+#include "TestScene.h"
namespace android {
namespace uirenderer {
@@ -25,20 +25,21 @@ namespace test {
class TestListViewSceneBase : public TestScene {
public:
- virtual void createListItem(RenderProperties& props, Canvas& canvas, int id,
- int itemWidth, int itemHeight) = 0;
+ virtual void createListItem(RenderProperties& props, Canvas& canvas, int id, int itemWidth,
+ int itemHeight) = 0;
+
private:
int mItemHeight;
int mItemSpacing;
int mItemWidth;
int mItemLeft;
sp<RenderNode> mListView;
- std::vector< sp<RenderNode> > mListItems;
+ std::vector<sp<RenderNode> > mListItems;
void createContent(int width, int height, Canvas& canvas) override;
void doFrame(int frameNr) override;
};
-} // namespace test
-} // namespace uirenderer
-} // namespace android
+} // namespace test
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/common/TestScene.h b/libs/hwui/tests/common/TestScene.h
index f6f7c62a4f63..91022cfe734b 100644
--- a/libs/hwui/tests/common/TestScene.h
+++ b/libs/hwui/tests/common/TestScene.h
@@ -16,6 +16,9 @@
#pragma once
+#include <gui/Surface.h>
+#include <utils/StrongPointer.h>
+
#include <string>
#include <unordered_map>
@@ -52,9 +55,8 @@ public:
class Registrar {
public:
- explicit Registrar(const TestScene::Info& info) {
- TestScene::registerScene(info);
- }
+ explicit Registrar(const TestScene::Info& info) { TestScene::registerScene(info); }
+
private:
Registrar() = delete;
Registrar(const Registrar&) = delete;
@@ -67,8 +69,10 @@ public:
static std::unordered_map<std::string, Info>& testMap();
static void registerScene(const Info& info);
+
+ sp<Surface> renderTarget;
};
-} // namespace test
-} // namespace uirenderer
-} // namespace android
+} // namespace test
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 64ec58d0adab..02ac97e0ed5c 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -16,16 +16,17 @@
#include "TestUtils.h"
-#include "hwui/Paint.h"
#include "DeferredLayerUpdater.h"
+#include "hwui/Paint.h"
-#include <renderthread/EglManager.h>
-#include <renderthread/OpenGLPipeline.h>
+#include <SkClipStack.h>
+#include <minikin/Layout.h>
#include <pipeline/skia/SkiaOpenGLPipeline.h>
#include <pipeline/skia/SkiaVulkanPipeline.h>
+#include <renderthread/EglManager.h>
+#include <renderthread/OpenGLPipeline.h>
#include <renderthread/VulkanManager.h>
#include <utils/Unicode.h>
-#include <SkClipStack.h>
#include <SkGlyphCache.h>
@@ -43,10 +44,10 @@ SkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end)
int endG = (end >> 8) & 0xff;
int endB = end & 0xff;
- return (int)((startA + (int)(fraction * (endA - startA))) << 24)
- | (int)((startR + (int)(fraction * (endR - startR))) << 16)
- | (int)((startG + (int)(fraction * (endG - startG))) << 8)
- | (int)((startB + (int)(fraction * (endB - startB))));
+ return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
+ (int)((startR + (int)(fraction * (endR - startR))) << 16) |
+ (int)((startG + (int)(fraction * (endG - startG))) << 8) |
+ (int)((startB + (int)(fraction * (endB - startB))));
}
sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
@@ -74,17 +75,18 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
layerUpdater->setTransform(&transform);
// updateLayer so it's ready to draw
- layerUpdater->updateLayer(true, Matrix4::identity().data);
+ layerUpdater->updateLayer(true, Matrix4::identity().data, HAL_DATASPACE_UNKNOWN);
if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
- static_cast<GlLayer*>(layerUpdater->backingLayer())->setRenderTarget(
- GL_TEXTURE_EXTERNAL_OES);
+ static_cast<GlLayer*>(layerUpdater->backingLayer())
+ ->setRenderTarget(GL_TEXTURE_EXTERNAL_OES);
}
return layerUpdater;
}
void TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text,
- std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions,
- float* outTotalAdvance, Rect* outBounds) {
+ std::vector<glyph_t>* outGlyphs,
+ std::vector<float>* outPositions, float* outTotalAdvance,
+ Rect* outBounds) {
Rect bounds;
float totalAdvance = 0;
SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
@@ -117,17 +119,22 @@ void TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text,
*outTotalAdvance = totalAdvance;
}
-
-void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text,
- const SkPaint& paint, float x, float y) {
+void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, float x,
+ float y) {
auto utf16 = asciiToUtf16(text);
- canvas->drawText(utf16.get(), 0, strlen(text), strlen(text), x, y, 0, paint, nullptr);
+ SkPaint glyphPaint(paint);
+ glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ canvas->drawText(utf16.get(), 0, strlen(text), strlen(text), x, y, minikin::Bidi::LTR,
+ glyphPaint, nullptr, nullptr /* measured text */);
}
-void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text,
- const SkPaint& paint, const SkPath& path) {
+void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint,
+ const SkPath& path) {
auto utf16 = asciiToUtf16(text);
- canvas->drawTextOnPath(utf16.get(), strlen(text), 0, path, 0, 0, paint, nullptr);
+ SkPaint glyphPaint(paint);
+ glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ canvas->drawTextOnPath(utf16.get(), strlen(text), minikin::Bidi::LTR, path, 0, 0, glyphPaint,
+ nullptr);
}
void TestUtils::TestTask::run() {
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index f29363131030..2752ae9a8036 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -22,11 +22,11 @@
#include <Properties.h>
#include <Rect.h>
#include <RenderNode.h>
+#include <Snapshot.h>
#include <hwui/Bitmap.h>
#include <pipeline/skia/SkiaRecordingCanvas.h>
#include <renderstate/RenderState.h>
#include <renderthread/RenderThread.h>
-#include <Snapshot.h>
#include <RecordedOp.h>
#include <RecordingCanvas.h>
@@ -36,85 +36,88 @@
namespace android {
namespace uirenderer {
-#define EXPECT_MATRIX_APPROX_EQ(a, b) \
- EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
-
-#define EXPECT_RECT_APPROX_EQ(a, b) \
- EXPECT_TRUE(MathUtils::areEqual((a).left, (b).left) \
- && MathUtils::areEqual((a).top, (b).top) \
- && MathUtils::areEqual((a).right, (b).right) \
- && MathUtils::areEqual((a).bottom, (b).bottom));
-
-#define EXPECT_CLIP_RECT(expRect, clipStatePtr) \
- EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped"; \
- if ((clipStatePtr)->mode == ClipMode::Rectangle) { \
- EXPECT_EQ((expRect), reinterpret_cast<const ClipRect*>(clipStatePtr)->rect); \
- } else { \
- ADD_FAILURE() << "ClipState not a rect"; \
- }
+#define EXPECT_MATRIX_APPROX_EQ(a, b) EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
+
+#define EXPECT_RECT_APPROX_EQ(a, b) \
+ EXPECT_TRUE(MathUtils::areEqual((a).left, (b).left) && \
+ MathUtils::areEqual((a).top, (b).top) && \
+ MathUtils::areEqual((a).right, (b).right) && \
+ MathUtils::areEqual((a).bottom, (b).bottom));
+
+#define EXPECT_CLIP_RECT(expRect, clipStatePtr) \
+ EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped"; \
+ if ((clipStatePtr)->mode == ClipMode::Rectangle) { \
+ EXPECT_EQ((expRect), reinterpret_cast<const ClipRect*>(clipStatePtr)->rect); \
+ } else { \
+ ADD_FAILURE() << "ClipState not a rect"; \
+ }
#define INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, functionCall) \
- TEST(test_case_name, test_name##_##pipeline) { \
- RenderPipelineType oldType = Properties::getRenderPipelineType(); \
- Properties::overrideRenderPipelineType(RenderPipelineType::pipeline); \
- functionCall; \
- Properties::overrideRenderPipelineType(oldType); \
+ TEST(test_case_name, test_name##_##pipeline) { \
+ RenderPipelineType oldType = Properties::getRenderPipelineType(); \
+ Properties::overrideRenderPipelineType(RenderPipelineType::pipeline); \
+ functionCall; \
+ Properties::overrideRenderPipelineType(oldType); \
};
/**
* Like gtests' TEST, but only runs with the OpenGL RenderPipelineType
*/
-#define OPENGL_PIPELINE_TEST(test_case_name, test_name) \
- class test_case_name##_##test_name##_HwuiTest { \
- public: \
- static void doTheThing(); \
- }; \
- INNER_PIPELINE_TEST(test_case_name, test_name, OpenGL, \
- test_case_name##_##test_name##_HwuiTest::doTheThing()) \
+#define OPENGL_PIPELINE_TEST(test_case_name, test_name) \
+ class test_case_name##_##test_name##_HwuiTest { \
+ public: \
+ static void doTheThing(); \
+ }; \
+ INNER_PIPELINE_TEST(test_case_name, test_name, OpenGL, \
+ test_case_name##_##test_name##_HwuiTest::doTheThing()) \
void test_case_name##_##test_name##_HwuiTest::doTheThing()
#define INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, pipeline) \
- INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, \
- TestUtils::runOnRenderThread(test_case_name##_##test_name##_RenderThreadTest::doTheThing))
+ INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, \
+ TestUtils::runOnRenderThread( \
+ test_case_name##_##test_name##_RenderThreadTest::doTheThing))
/**
* Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope
* (for e.g. accessing its RenderState)
*/
-#define RENDERTHREAD_TEST(test_case_name, test_name) \
- class test_case_name##_##test_name##_RenderThreadTest { \
- public: \
- static void doTheThing(renderthread::RenderThread& renderThread); \
- }; \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
+#define RENDERTHREAD_TEST(test_case_name, test_name) \
+ class test_case_name##_##test_name##_RenderThreadTest { \
+ public: \
+ static void doTheThing(renderthread::RenderThread& renderThread); \
+ }; \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
/* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
- /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
- void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread)
+ /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
+ void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \
+ renderthread::RenderThread& renderThread)
/**
* Like RENDERTHREAD_TEST, but only runs with the OpenGL RenderPipelineType
*/
-#define RENDERTHREAD_OPENGL_PIPELINE_TEST(test_case_name, test_name) \
- class test_case_name##_##test_name##_RenderThreadTest { \
- public: \
+#define RENDERTHREAD_OPENGL_PIPELINE_TEST(test_case_name, test_name) \
+ class test_case_name##_##test_name##_RenderThreadTest { \
+ public: \
static void doTheThing(renderthread::RenderThread& renderThread); \
- }; \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \
- void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread)
+ }; \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \
+ void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \
+ renderthread::RenderThread& renderThread)
/**
* Like RENDERTHREAD_TEST, but only runs with the Skia RenderPipelineTypes
*/
-#define RENDERTHREAD_SKIA_PIPELINE_TEST(test_case_name, test_name) \
- class test_case_name##_##test_name##_RenderThreadTest { \
- public: \
- static void doTheThing(renderthread::RenderThread& renderThread); \
- }; \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
+#define RENDERTHREAD_SKIA_PIPELINE_TEST(test_case_name, test_name) \
+ class test_case_name##_##test_name##_RenderThreadTest { \
+ public: \
+ static void doTheThing(renderthread::RenderThread& renderThread); \
+ }; \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
/* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
- /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
- void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread)
+ /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
+ void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \
+ renderthread::RenderThread& renderThread)
/**
* Sets a property value temporarily, generally for the duration of a test, restoring the previous
@@ -125,14 +128,11 @@ namespace uirenderer {
template <typename T>
class ScopedProperty {
public:
- ScopedProperty(T& property, T newValue)
- : mPropertyPtr(&property)
- , mOldValue(property) {
+ ScopedProperty(T& property, T newValue) : mPropertyPtr(&property), mOldValue(property) {
property = newValue;
}
- ~ScopedProperty() {
- *mPropertyPtr = mOldValue;
- }
+ ~ScopedProperty() { *mPropertyPtr = mOldValue; }
+
private:
T* mPropertyPtr;
T mOldValue;
@@ -142,18 +142,15 @@ class TestUtils {
public:
class SignalingDtor {
public:
- SignalingDtor()
- : mSignal(nullptr) {}
- explicit SignalingDtor(int* signal)
- : mSignal(signal) {}
- void setSignal(int* signal) {
- mSignal = signal;
- }
+ SignalingDtor() : mSignal(nullptr) {}
+ explicit SignalingDtor(int* signal) : mSignal(signal) {}
+ void setSignal(int* signal) { mSignal = signal; }
~SignalingDtor() {
if (mSignal) {
(*mSignal)++;
}
}
+
private:
int* mSignal;
};
@@ -181,7 +178,7 @@ public:
}
static sk_sp<Bitmap> createBitmap(int width, int height,
- SkColorType colorType = kN32_SkColorType) {
+ SkColorType colorType = kN32_SkColorType) {
SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType);
return Bitmap::allocateHeapBitmap(info);
}
@@ -199,15 +196,16 @@ public:
renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
const SkMatrix& transform);
- template<class CanvasType>
- static std::unique_ptr<DisplayList> createDisplayList(int width, int height,
- std::function<void(CanvasType& canvas)> canvasCallback) {
+ template <class CanvasType>
+ static std::unique_ptr<DisplayList> createDisplayList(
+ int width, int height, std::function<void(CanvasType& canvas)> canvasCallback) {
CanvasType canvas(width, height);
canvasCallback(canvas);
return std::unique_ptr<DisplayList>(canvas.finishRecording());
}
- static sp<RenderNode> createNode(int left, int top, int right, int bottom,
+ static sp<RenderNode> createNode(
+ int left, int top, int right, int bottom,
std::function<void(RenderProperties& props, Canvas& canvas)> setup) {
#if HWUI_NULL_GPU
// if RenderNodes are being sync'd/used, device info will be needed, since
@@ -219,8 +217,8 @@ public:
RenderProperties& props = node->mutateStagingProperties();
props.setLeftTopRightBottom(left, top, right, bottom);
if (setup) {
- std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(props.getWidth(),
- props.getHeight()));
+ std::unique_ptr<Canvas> canvas(
+ Canvas::create_recording_canvas(props.getWidth(), props.getHeight()));
setup(props, *canvas.get());
node->setStagingDisplayList(canvas->finishRecording());
}
@@ -228,8 +226,9 @@ public:
return node;
}
- template<class RecordingCanvasType>
- static sp<RenderNode> createNode(int left, int top, int right, int bottom,
+ template <class RecordingCanvasType>
+ static sp<RenderNode> createNode(
+ int left, int top, int right, int bottom,
std::function<void(RenderProperties& props, RecordingCanvasType& canvas)> setup) {
#if HWUI_NULL_GPU
// if RenderNodes are being sync'd/used, device info will be needed, since
@@ -249,22 +248,24 @@ public:
return node;
}
- static void recordNode(RenderNode& node,
- std::function<void(Canvas&)> contentCallback) {
- std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- node.stagingProperties().getWidth(), node.stagingProperties().getHeight()));
- contentCallback(*canvas.get());
- node.setStagingDisplayList(canvas->finishRecording());
+ static void recordNode(RenderNode& node, std::function<void(Canvas&)> contentCallback) {
+ std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
+ node.stagingProperties().getWidth(), node.stagingProperties().getHeight(),
+ &node));
+ contentCallback(*canvas.get());
+ node.setStagingDisplayList(canvas->finishRecording());
}
- static sp<RenderNode> createSkiaNode(int left, int top, int right, int bottom,
- std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)> setup,
+ static sp<RenderNode> createSkiaNode(
+ int left, int top, int right, int bottom,
+ std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)>
+ setup,
const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) {
- #if HWUI_NULL_GPU
+#if HWUI_NULL_GPU
// if RenderNodes are being sync'd/used, device info will be needed, since
// DeviceInfo::maxTextureSize() affects layer property
DeviceInfo::initialize();
- #endif
+#endif
sp<RenderNode> node = new RenderNode();
if (name) {
node->setName(name);
@@ -276,8 +277,8 @@ public:
}
if (setup) {
std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas(
- new skiapipeline::SkiaRecordingCanvas(nullptr,
- props.getWidth(), props.getHeight()));
+ new skiapipeline::SkiaRecordingCanvas(nullptr, props.getWidth(),
+ props.getHeight()));
setup(props, *canvas.get());
node->setStagingDisplayList(canvas->finishRecording());
}
@@ -306,8 +307,7 @@ public:
class TestTask : public renderthread::RenderTask {
public:
- explicit TestTask(RtCallback rtCallback)
- : rtCallback(rtCallback) {}
+ explicit TestTask(RtCallback rtCallback) : rtCallback(rtCallback) {}
virtual ~TestTask() {}
virtual void run() override;
RtCallback rtCallback;
@@ -318,37 +318,37 @@ public:
*/
static void runOnRenderThread(RtCallback rtCallback) {
TestTask task(rtCallback);
- renderthread::RenderThread::getInstance().queueAndWait(&task);
+ renderthread::RenderThread::getInstance().queue().runSync([&]() { task.run(); });
}
- static bool isRenderThreadRunning() {
- return renderthread::RenderThread::hasInstance();
- }
+ static bool isRenderThreadRunning() { return renderthread::RenderThread::hasInstance(); }
static SkColor interpolateColor(float fraction, SkColor start, SkColor end);
static void layoutTextUnscaled(const SkPaint& paint, const char* text,
- std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions,
- float* outTotalAdvance, Rect* outBounds);
+ std::vector<glyph_t>* outGlyphs,
+ std::vector<float>* outPositions, float* outTotalAdvance,
+ Rect* outBounds);
- static void drawUtf8ToCanvas(Canvas* canvas, const char* text,
- const SkPaint& paint, float x, float y);
+ static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, float x,
+ float y);
- static void drawUtf8ToCanvas(Canvas* canvas, const char* text,
- const SkPaint& paint, const SkPath& path);
+ static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint,
+ const SkPath& path);
static std::unique_ptr<uint16_t[]> asciiToUtf16(const char* str);
class MockFunctor : public Functor {
- public:
- virtual status_t operator ()(int what, void* data) {
- mLastMode = what;
- return DrawGlInfo::kStatusDone;
- }
- int getLastMode() const { return mLastMode; }
- private:
- int mLastMode = -1;
- };
+ public:
+ virtual status_t operator()(int what, void* data) {
+ mLastMode = what;
+ return DrawGlInfo::kStatusDone;
+ }
+ int getLastMode() const { return mLastMode; }
+
+ private:
+ int mLastMode = -1;
+ };
static SkColor getColor(const sk_sp<SkSurface>& surface, int x, int y);
@@ -367,7 +367,8 @@ private:
if (displayList) {
if (displayList->isSkiaDL()) {
for (auto&& childDr : static_cast<skiapipeline::SkiaDisplayList*>(
- const_cast<DisplayList*>(displayList))->mChildNodes) {
+ const_cast<DisplayList*>(displayList))
+ ->mChildNodes) {
syncHierarchyPropertiesAndDisplayListImpl(childDr.getRenderNode());
}
} else {
@@ -378,7 +379,7 @@ private:
}
}
-}; // class TestUtils
+}; // class TestUtils
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/tests/common/scenes/BitmapFillrate.cpp b/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
index be58d09b7f4d..1d3d60716d68 100644
--- a/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
@@ -32,8 +32,7 @@ static bool _BitmapFillrate(
class BitmapFillrate : public TestScene {
public:
BitmapFillrate(BitmapAllocationTestUtils::BitmapAllocator allocator)
- : TestScene()
- , mAllocator(allocator) { }
+ : TestScene(), mAllocator(allocator) {}
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
@@ -41,7 +40,7 @@ public:
createNode(canvas, 0xA0CDDC39, width / 3, height / 3, width, height);
createNode(canvas, 0x90009688, width / 3, 0, width, height);
createNode(canvas, 0xA0FF5722, 0, height / 3, width, height);
- createNode(canvas, 0x9000796B, width / 6, height/6, width, height);
+ createNode(canvas, 0x9000796B, width / 6, height / 6, width, height);
createNode(canvas, 0xA0FFC107, width / 6, 0, width, height);
}
@@ -52,23 +51,23 @@ public:
mNodes[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
}
+
private:
- void createNode(Canvas& canvas, SkColor color, int left, int top,
- int width, int height) {
+ void createNode(Canvas& canvas, SkColor color, int left, int top, int width, int height) {
int itemWidth = 2 * width / 3;
int itemHeight = 2 * height / 3;
- auto card = TestUtils::createNode(left, top, left + itemWidth , top + itemHeight,
+ auto card = TestUtils::createNode(
+ left, top, left + itemWidth, top + itemHeight,
[this, itemWidth, itemHeight, color](RenderProperties& props, Canvas& canvas) {
- sk_sp<Bitmap> bitmap = mAllocator(itemWidth, itemHeight, kRGBA_8888_SkColorType,
- [color](SkBitmap& skBitmap) {
- skBitmap.eraseColor(color);
- });
- canvas.drawBitmap(*bitmap, 0, 0, nullptr);
- });
+ sk_sp<Bitmap> bitmap =
+ mAllocator(itemWidth, itemHeight, kRGBA_8888_SkColorType,
+ [color](SkBitmap& skBitmap) { skBitmap.eraseColor(color); });
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ });
canvas.drawRenderNode(card.get());
mNodes.push_back(card);
}
BitmapAllocationTestUtils::BitmapAllocator mAllocator;
- std::vector< sp<RenderNode> > mNodes;
+ std::vector<sp<RenderNode> > mNodes;
}; \ No newline at end of file
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index 4797dec8e89e..15039b5fa976 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -14,55 +14,52 @@
* limitations under the License.
*/
+#include <SkImagePriv.h>
#include "TestSceneBase.h"
-#include "utils/Color.h"
#include "tests/common/BitmapAllocationTestUtils.h"
-#include <SkImagePriv.h>
+#include "utils/Color.h"
class BitmapShaders;
-static bool _BitmapShaders(
- BitmapAllocationTestUtils::registerBitmapAllocationScene<BitmapShaders>(
- "bitmapShader", "Draws bitmap shaders with repeat and mirror modes."));
+static bool _BitmapShaders(BitmapAllocationTestUtils::registerBitmapAllocationScene<BitmapShaders>(
+ "bitmapShader", "Draws bitmap shaders with repeat and mirror modes."));
class BitmapShaders : public TestScene {
public:
BitmapShaders(BitmapAllocationTestUtils::BitmapAllocator allocator)
- : TestScene()
- , mAllocator(allocator) { }
+ : TestScene(), mAllocator(allocator) {}
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::Grey_200, SkBlendMode::kSrcOver);
- sk_sp<Bitmap> hwuiBitmap = mAllocator(200, 200, kRGBA_8888_SkColorType,
- [](SkBitmap& skBitmap) {
- skBitmap.eraseColor(Color::White);
- SkCanvas skCanvas(skBitmap);
- SkPaint skPaint;
- skPaint.setColor(Color::Red_500);
- skCanvas.drawRect(SkRect::MakeWH(100, 100), skPaint);
- skPaint.setColor(Color::Blue_500);
- skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
- });
+ sk_sp<Bitmap> hwuiBitmap =
+ mAllocator(200, 200, kRGBA_8888_SkColorType, [](SkBitmap& skBitmap) {
+ skBitmap.eraseColor(Color::White);
+ SkCanvas skCanvas(skBitmap);
+ SkPaint skPaint;
+ skPaint.setColor(Color::Red_500);
+ skCanvas.drawRect(SkRect::MakeWH(100, 100), skPaint);
+ skPaint.setColor(Color::Blue_500);
+ skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
+ });
SkPaint paint;
- sk_sp<SkImage> image = hwuiBitmap->makeImage();
- sk_sp<SkShader> repeatShader = image->makeShader(
- SkShader::TileMode::kRepeat_TileMode,
- SkShader::TileMode::kRepeat_TileMode,
- nullptr);
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = hwuiBitmap->makeImage(&colorFilter);
+ sk_sp<SkShader> repeatShader =
+ image->makeShader(SkShader::TileMode::kRepeat_TileMode,
+ SkShader::TileMode::kRepeat_TileMode, nullptr);
paint.setShader(std::move(repeatShader));
canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
- sk_sp<SkShader> mirrorShader = image->makeShader(
- SkShader::TileMode::kMirror_TileMode,
- SkShader::TileMode::kMirror_TileMode,
- nullptr);
+ sk_sp<SkShader> mirrorShader =
+ image->makeShader(SkShader::TileMode::kMirror_TileMode,
+ SkShader::TileMode::kMirror_TileMode, nullptr);
paint.setShader(std::move(mirrorShader));
canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
}
- void doFrame(int frameNr) override { }
+ void doFrame(int frameNr) override {}
BitmapAllocationTestUtils::BitmapAllocator mAllocator;
};
diff --git a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
index f47e05a1f3e6..2a016ac1b5bc 100644
--- a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
@@ -19,19 +19,17 @@
class ClippingAnimation;
static TestScene::Registrar _RectGrid(TestScene::Info{
- "clip",
- "Complex clip cases"
- "Low CPU/GPU load.",
- TestScene::simpleCreateScene<ClippingAnimation>
-});
+ "clip",
+ "Complex clip cases"
+ "Low CPU/GPU load.",
+ TestScene::simpleCreateScene<ClippingAnimation>});
class ClippingAnimation : public TestScene {
public:
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
- card = TestUtils::createNode(0, 0, 200, 400,
- [](RenderProperties& props, Canvas& canvas) {
+ card = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
{
canvas.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index 5b685bb2f3f7..f0a5e9dff1b9 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -25,39 +25,34 @@
class GlyphStressAnimation;
static TestScene::Registrar _GlyphStress(TestScene::Info{
- "glyphstress",
- "A stress test for both the glyph cache, and glyph rendering.",
- TestScene::simpleCreateScene<GlyphStressAnimation>
-});
+ "glyphstress", "A stress test for both the glyph cache, and glyph rendering.",
+ TestScene::simpleCreateScene<GlyphStressAnimation>});
class GlyphStressAnimation : public TestScene {
public:
sp<RenderNode> container;
void createContent(int width, int height, Canvas& canvas) override {
container = TestUtils::createNode(0, 0, width, height, nullptr);
- doFrame(0); // update container
+ doFrame(0); // update container
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
canvas.drawRenderNode(container.get());
}
void doFrame(int frameNr) override {
- std::unique_ptr<uint16_t[]> text = TestUtils::asciiToUtf16(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
- ssize_t textLength = 26 * 2;
+ const char* text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
- std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- container->stagingProperties().getWidth(),
- container->stagingProperties().getHeight()));
+ std::unique_ptr<Canvas> canvas(
+ Canvas::create_recording_canvas(container->stagingProperties().getWidth(),
+ container->stagingProperties().getHeight(),
+ container.get()));
Paint paint;
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setAntiAlias(true);
paint.setColor(Color::Black);
for (int i = 0; i < 5; i++) {
paint.setTextSize(10 + (frameNr % 20) + i * 20);
- canvas->drawText(text.get(), 0, textLength, textLength,
- 0, 100 * (i + 2), minikin::kBidi_Force_LTR, paint, nullptr);
+ TestUtils::drawUtf8ToCanvas(canvas.get(), text, paint, 0, 100 * (i + 2));
}
container->setStagingDisplayList(canvas->finishRecording());
diff --git a/libs/hwui/tests/common/scenes/HwBitmap565.cpp b/libs/hwui/tests/common/scenes/HwBitmap565.cpp
index 18fea3d1cb81..cbdb756b8fa7 100644
--- a/libs/hwui/tests/common/scenes/HwBitmap565.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmap565.cpp
@@ -15,16 +15,14 @@
*/
#include "TestSceneBase.h"
-#include "utils/Color.h"
#include "tests/common/BitmapAllocationTestUtils.h"
+#include "utils/Color.h"
class HwBitmap565;
static TestScene::Registrar _HwBitmap565(TestScene::Info{
- "hwBitmap565",
- "Draws composite shader with hardware bitmap",
- TestScene::simpleCreateScene<HwBitmap565>
-});
+ "hwBitmap565", "Draws composite shader with hardware bitmap",
+ TestScene::simpleCreateScene<HwBitmap565>});
class HwBitmap565 : public TestScene {
public:
@@ -32,18 +30,18 @@ public:
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::Grey_200, SkBlendMode::kSrcOver);
- sk_sp<Bitmap> hardwareBitmap = BitmapAllocationTestUtils::allocateHardwareBitmap(200, 200,
- kRGB_565_SkColorType, [](SkBitmap& skBitmap) {
- skBitmap.eraseColor(Color::White);
- SkCanvas skCanvas(skBitmap);
- SkPaint skPaint;
- skPaint.setColor(Color::Red_500);
- skCanvas.drawRect(SkRect::MakeWH(100, 100), skPaint);
- skPaint.setColor(Color::Blue_500);
- skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
- });
+ sk_sp<Bitmap> hardwareBitmap = BitmapAllocationTestUtils::allocateHardwareBitmap(
+ 200, 200, kRGB_565_SkColorType, [](SkBitmap& skBitmap) {
+ skBitmap.eraseColor(Color::White);
+ SkCanvas skCanvas(skBitmap);
+ SkPaint skPaint;
+ skPaint.setColor(Color::Red_500);
+ skCanvas.drawRect(SkRect::MakeWH(100, 100), skPaint);
+ skPaint.setColor(Color::Blue_500);
+ skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
+ });
canvas.drawBitmap(*hardwareBitmap, 10.0f, 10.0f, nullptr);
}
- void doFrame(int frameNr) override { }
+ void doFrame(int frameNr) override {}
}; \ No newline at end of file
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index c246ebaddcad..f137562e7c73 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -17,17 +17,15 @@
#include "TestSceneBase.h"
#include "utils/Color.h"
-#include <ui/PixelFormat.h>
#include <SkGradientShader.h>
#include <SkImagePriv.h>
+#include <ui/PixelFormat.h>
class HwBitmapInCompositeShader;
static TestScene::Registrar _HwBitmapInCompositeShader(TestScene::Info{
- "hwbitmapcompositeshader",
- "Draws composite shader with hardware bitmap",
- TestScene::simpleCreateScene<HwBitmapInCompositeShader>
-});
+ "hwbitmapcompositeshader", "Draws composite shader with hardware bitmap",
+ TestScene::simpleCreateScene<HwBitmapInCompositeShader>});
class HwBitmapInCompositeShader : public TestScene {
public:
@@ -35,16 +33,15 @@ public:
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
- uint32_t usage = GraphicBuffer::USAGE_HW_TEXTURE
- | GraphicBuffer::USAGE_SW_READ_NEVER
- | GRALLOC_USAGE_SW_WRITE_RARELY;
+ uint32_t usage = GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_READ_NEVER |
+ GRALLOC_USAGE_SW_WRITE_RARELY;
sp<GraphicBuffer> buffer = new GraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, usage);
unsigned char* pixels = nullptr;
buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, ((void**)&pixels));
- size_t size = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride()
- * buffer->getHeight();
+ size_t size =
+ bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride() * buffer->getHeight();
memset(pixels, 0, size);
for (int i = 0; i < 6000; i++) {
pixels[4000 + 4 * i + 0] = 255;
@@ -61,8 +58,8 @@ public:
SkColor colors[2];
colors[0] = Color::Black;
colors[1] = Color::White;
- sk_sp<SkShader> gradientShader = SkGradientShader::MakeRadial(center, 50, colors, nullptr,
- 2, SkShader::TileMode::kRepeat_TileMode);
+ sk_sp<SkShader> gradientShader = SkGradientShader::MakeRadial(
+ center, 50, colors, nullptr, 2, SkShader::TileMode::kRepeat_TileMode);
sk_sp<SkShader> compositeShader(
SkShader::MakeComposeShader(hardwareShader, gradientShader, SkBlendMode::kDstATop));
@@ -72,11 +69,12 @@ public:
canvas.drawRoundRect(0, 0, 400, 200, 10.0f, 10.0f, paint);
}
- void doFrame(int frameNr) override { }
+ void doFrame(int frameNr) override {}
sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
- sk_sp<SkImage> image = bitmap.makeImage();
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
return image->makeShader(SkShader::TileMode::kClamp_TileMode,
- SkShader::TileMode::kClamp_TileMode);
+ SkShader::TileMode::kClamp_TileMode);
}
};
diff --git a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
index 3a230ae6e8b7..cac2fb3d8d5c 100644
--- a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
@@ -19,22 +19,20 @@
class HwLayerAnimation;
static TestScene::Registrar _HwLayer(TestScene::Info{
- "hwlayer",
- "A nested pair of nodes with LAYER_TYPE_HARDWARE set on each. "
- "Tests the hardware layer codepath.",
- TestScene::simpleCreateScene<HwLayerAnimation>
-});
+ "hwlayer",
+ "A nested pair of nodes with LAYER_TYPE_HARDWARE set on each. "
+ "Tests the hardware layer codepath.",
+ TestScene::simpleCreateScene<HwLayerAnimation>});
class HwLayerAnimation : public TestScene {
public:
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
- card = TestUtils::createNode(0, 0, 200, 200,
- [](RenderProperties& props, Canvas& canvas) {
+ card = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
props.mutateLayerProperties().setType(LayerType::RenderLayer);
canvas.drawColor(0xFF0000FF, SkBlendMode::kSrcOver);
});
- canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver); // background
+ canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver); // background
canvas.drawRenderNode(card.get());
}
void doFrame(int frameNr) override {
diff --git a/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp
index d84113238e53..77a59dfe6ba5 100644
--- a/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp
@@ -19,29 +19,27 @@
class HwLayerSizeAnimation;
static TestScene::Registrar _HwLayerSize(TestScene::Info{
- "hwlayersize",
- "A nested pair of nodes with LayerType::RenderLayer(hardware) set on the child and "
- "LayerType::None on the parent. "
- "Tests animating the size of a hardware layer.",
- TestScene::simpleCreateScene<HwLayerSizeAnimation>
-});
+ "hwlayersize",
+ "A nested pair of nodes with LayerType::RenderLayer(hardware) set on the child and "
+ "LayerType::None on the parent. "
+ "Tests animating the size of a hardware layer.",
+ TestScene::simpleCreateScene<HwLayerSizeAnimation>});
class HwLayerSizeAnimation : public TestScene {
public:
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
- card = TestUtils::createNode(0, 0, 200, 200,
- [](RenderProperties& props, Canvas& canvas) {
+ card = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
props.mutateLayerProperties().setType(LayerType::RenderLayer);
canvas.drawColor(0xFF0000FF, SkBlendMode::kSrcOver);
});
- canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver); // background
+ canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver); // background
canvas.drawRenderNode(card.get());
}
void doFrame(int frameNr) override {
int curFrame = frameNr % 150;
- //we animate left and top coordinates, which in turn animates width and
- //height (bottom/right coordinates are fixed)
+ // we animate left and top coordinates, which in turn animates width and
+ // height (bottom/right coordinates are fixed)
card->mutateStagingProperties().setLeftTop(curFrame, curFrame);
card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
diff --git a/libs/hwui/tests/common/scenes/JankyScene.cpp b/libs/hwui/tests/common/scenes/JankyScene.cpp
new file mode 100644
index 000000000000..f5e6b317529a
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/JankyScene.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestSceneBase.h"
+
+#include <unistd.h>
+
+class JankyScene;
+
+static TestScene::Registrar _JankyScene(TestScene::Info{
+ "janky",
+ "A scene that intentionally janks just enough to stay in "
+ "triple buffering.",
+ TestScene::simpleCreateScene<JankyScene>});
+
+class JankyScene : public TestScene {
+public:
+ sp<RenderNode> card;
+
+ void createContent(int width, int height, Canvas& canvas) override {
+ card = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(0xFF0000FF, SkBlendMode::kSrcOver);
+ });
+ canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver); // background
+ canvas.drawRenderNode(card.get());
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ if (curFrame & 1) {
+ usleep(15000);
+ }
+ // we animate left and top coordinates, which in turn animates width and
+ // height (bottom/right coordinates are fixed)
+ card->mutateStagingProperties().setLeftTop(curFrame, curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+}; \ No newline at end of file
diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
index b7357e179bfe..58c99800875b 100644
--- a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
@@ -22,15 +22,14 @@
class ListOfFadedTextAnimation;
static TestScene::Registrar _ListOfFadedTextAnimation(TestScene::Info{
- "fadingedges",
- "A mock ListView of scrolling text with faded edge. Doesn't re-bind/re-record views"
- "as they are recycled, so won't upload much content (either glyphs, or bitmaps).",
- TestScene::simpleCreateScene<ListOfFadedTextAnimation>
-});
+ "fadingedges",
+ "A mock ListView of scrolling text with faded edge. Doesn't re-bind/re-record views"
+ "as they are recycled, so won't upload much content (either glyphs, or bitmaps).",
+ TestScene::simpleCreateScene<ListOfFadedTextAnimation>});
class ListOfFadedTextAnimation : public TestListViewSceneBase {
- void createListItem(RenderProperties& props, Canvas& canvas, int id,
- int itemWidth, int itemHeight) override {
+ void createListItem(RenderProperties& props, Canvas& canvas, int id, int itemWidth,
+ int itemHeight) override {
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
int length = dp(100);
canvas.saveLayer(0, 0, length, itemHeight, nullptr, SaveFlags::HasAlphaLayer);
@@ -44,8 +43,8 @@ class ListOfFadedTextAnimation : public TestListViewSceneBase {
pts[1].set(0, 1);
SkColor colors[2] = {Color::Black, Color::Transparent};
- sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, NULL, 2,
- SkShader::kClamp_TileMode));
+ sk_sp<SkShader> s(
+ SkGradientShader::MakeLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode));
SkMatrix matrix;
matrix.setScale(1, length);
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index c1144be5b57c..fd8c252ff318 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -22,11 +22,11 @@
class ListViewAnimation;
static TestScene::Registrar _ListView(TestScene::Info{
- "listview",
- "A mock ListView of scrolling content. Doesn't re-bind/re-record views as they are recycled, so"
- "won't upload much content (either glyphs, or bitmaps).",
- TestScene::simpleCreateScene<ListViewAnimation>
-});
+ "listview",
+ "A mock ListView of scrolling content. Doesn't re-bind/re-record views as they are "
+ "recycled, so"
+ "won't upload much content (either glyphs, or bitmaps).",
+ TestScene::simpleCreateScene<ListViewAnimation>});
class ListViewAnimation : public TestListViewSceneBase {
sk_sp<Bitmap> createRandomCharIcon(int cardHeight) {
@@ -42,15 +42,15 @@ class ListViewAnimation : public TestListViewSceneBase {
paint.setColor(randomColor);
canvas.drawCircle(size / 2, size / 2, size / 2, paint);
- bool bgDark = SkColorGetR(randomColor) + SkColorGetG(randomColor) + SkColorGetB(randomColor)
- < 128 * 3;
+ bool bgDark =
+ SkColorGetR(randomColor) + SkColorGetG(randomColor) + SkColorGetB(randomColor) <
+ 128 * 3;
paint.setColor(bgDark ? Color::White : Color::Grey_700);
paint.setTextAlign(SkPaint::kCenter_Align);
paint.setTextSize(size / 2);
char charToShow = 'A' + (rand() % 26);
- const SkPoint pos[] = {{
- SkIntToScalar(size / 2),
- /*approximate centering*/ SkFloatToScalar(size * 0.7f)}};
+ const SkPoint pos[] = {{SkIntToScalar(size / 2),
+ /*approximate centering*/ SkFloatToScalar(size * 0.7f)}};
canvas.drawPosText(&charToShow, 1, pos, paint);
return bitmap;
}
@@ -72,8 +72,8 @@ class ListViewAnimation : public TestListViewSceneBase {
return bitmap;
}
- void createListItem(RenderProperties& props, Canvas& canvas, int cardId,
- int itemWidth, int itemHeight) override {
+ void createListItem(RenderProperties& props, Canvas& canvas, int cardId, int itemWidth,
+ int itemHeight) override {
static sk_sp<Bitmap> filledBox(createBoxBitmap(true));
static sk_sp<Bitmap> strokedBox(createBoxBitmap(false));
// TODO: switch to using round rect clipping, once merging correctly handles that
@@ -83,7 +83,6 @@ class ListViewAnimation : public TestListViewSceneBase {
canvas.drawRoundRect(0, 0, itemWidth, itemHeight, dp(6), dp(6), roundRectPaint);
SkPaint textPaint;
- textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
textPaint.setTextSize(dp(20));
textPaint.setAntiAlias(true);
@@ -92,7 +91,7 @@ class ListViewAnimation : public TestListViewSceneBase {
TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, itemHeight, dp(25));
textPaint.setTextSize(dp(15));
TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
- itemHeight, dp(45));
+ itemHeight, dp(45));
auto randomIcon = createRandomCharIcon(itemHeight);
canvas.drawBitmap(*randomIcon, dp(10), dp(10), nullptr);
diff --git a/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp b/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp
new file mode 100644
index 000000000000..aa537b4f329c
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestSceneBase.h"
+#include "renderthread/RenderProxy.h"
+#include "utils/Color.h"
+
+class MagnifierAnimation;
+
+static TestScene::Registrar _Magnifier(TestScene::Info{
+ "magnifier", "A sample magnifier using Readback",
+ TestScene::simpleCreateScene<MagnifierAnimation>});
+
+class MagnifierAnimation : public TestScene {
+public:
+ sp<RenderNode> card;
+ sp<RenderNode> zoomImageView;
+
+ void createContent(int width, int height, Canvas& canvas) override {
+ magnifier = TestUtils::createBitmap(200, 100);
+ SkBitmap temp;
+ magnifier->getSkBitmap(&temp);
+ temp.eraseColor(Color::White);
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+ card = TestUtils::createNode(
+ 0, 0, width, height, [&](RenderProperties& props, Canvas& canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(50);
+
+ paint.setColor(Color::Black);
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string", paint, 10, 400);
+ });
+ canvas.drawRenderNode(card.get());
+ zoomImageView = TestUtils::createNode(
+ 100, 100, 500, 300, [&](RenderProperties& props, Canvas& canvas) {
+ props.setElevation(dp(16));
+ props.mutableOutline().setRoundRect(0, 0, props.getWidth(), props.getHeight(),
+ dp(6), 1);
+ props.mutableOutline().setShouldClip(true);
+ canvas.drawBitmap(*magnifier, 0.0f, 0.0f, (float)magnifier->width(),
+ (float)magnifier->height(), 0, 0, (float)props.getWidth(),
+ (float)props.getHeight(), nullptr);
+ });
+ canvas.insertReorderBarrier(true);
+ canvas.drawRenderNode(zoomImageView.get());
+ canvas.insertReorderBarrier(false);
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ if (renderTarget) {
+ SkBitmap temp;
+ magnifier->getSkBitmap(&temp);
+ constexpr int x = 90;
+ constexpr int y = 325;
+ RenderProxy::copySurfaceInto(renderTarget, x, y, x + magnifier->width(),
+ y + magnifier->height(), &temp);
+ }
+ }
+
+ sk_sp<Bitmap> magnifier;
+};
diff --git a/libs/hwui/tests/common/scenes/OpPropAnimation.cpp b/libs/hwui/tests/common/scenes/OpPropAnimation.cpp
index 68051d63e855..a24cae0ecf8a 100644
--- a/libs/hwui/tests/common/scenes/OpPropAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/OpPropAnimation.cpp
@@ -20,10 +20,8 @@
class OpPropAnimation;
static TestScene::Registrar _Shapes(TestScene::Info{
- "opprops",
- "A minimal demonstration of CanvasProperty drawing operations.",
- TestScene::simpleCreateScene<OpPropAnimation>
-});
+ "opprops", "A minimal demonstration of CanvasProperty drawing operations.",
+ TestScene::simpleCreateScene<OpPropAnimation>});
class OpPropAnimation : public TestScene {
public:
@@ -42,8 +40,9 @@ public:
sp<RenderNode> content;
void createContent(int width, int height, Canvas& canvas) override {
- content = TestUtils::createNode(0, 0, width, height,
- [this, width, height](RenderProperties& props, Canvas& canvas) {
+ content = TestUtils::createNode(0, 0, width, height, [this, width, height](
+ RenderProperties& props,
+ Canvas& canvas) {
mPaint->value.setAntiAlias(true);
mPaint->value.setColor(Color::Blue_500);
@@ -54,9 +53,9 @@ public:
mCircleY->value = height * 0.75;
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
- canvas.drawRoundRect(mRoundRectLeft.get(), mRoundRectTop.get(),
- mRoundRectRight.get(), mRoundRectBottom.get(),
- mRoundRectRx.get(), mRoundRectRy.get(), mPaint.get());
+ canvas.drawRoundRect(mRoundRectLeft.get(), mRoundRectTop.get(), mRoundRectRight.get(),
+ mRoundRectBottom.get(), mRoundRectRx.get(), mRoundRectRy.get(),
+ mPaint.get());
canvas.drawCircle(mCircleX.get(), mCircleY.get(), mCircleRadius.get(), mPaint.get());
});
canvas.drawRenderNode(content.get());
diff --git a/libs/hwui/tests/common/scenes/OvalAnimation.cpp b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
index d6fd60494812..4ff868b9d068 100644
--- a/libs/hwui/tests/common/scenes/OvalAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
@@ -19,19 +19,15 @@
class OvalAnimation;
-static TestScene::Registrar _Oval(TestScene::Info{
- "oval",
- "Draws 1 oval.",
- TestScene::simpleCreateScene<OvalAnimation>
-});
+static TestScene::Registrar _Oval(TestScene::Info{"oval", "Draws 1 oval.",
+ TestScene::simpleCreateScene<OvalAnimation>});
class OvalAnimation : public TestScene {
public:
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
- card = TestUtils::createNode(0, 0, 200, 200,
- [](RenderProperties& props, Canvas& canvas) {
+ card = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setColor(Color::Black);
diff --git a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
index bc04d81296df..fb1b000a995e 100644
--- a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
@@ -19,22 +19,18 @@
class PartialDamageAnimation;
static TestScene::Registrar _PartialDamage(TestScene::Info{
- "partialdamage",
- "Tests the partial invalidation path. Draws a grid of rects and animates 1 "
- "of them, should be low CPU & GPU load if EGL_EXT_buffer_age or "
- "EGL_KHR_partial_update is supported by the device & are enabled in hwui.",
- TestScene::simpleCreateScene<PartialDamageAnimation>
-});
+ "partialdamage",
+ "Tests the partial invalidation path. Draws a grid of rects and animates 1 "
+ "of them, should be low CPU & GPU load if EGL_EXT_buffer_age or "
+ "EGL_KHR_partial_update is supported by the device & are enabled in hwui.",
+ TestScene::simpleCreateScene<PartialDamageAnimation>});
class PartialDamageAnimation : public TestScene {
public:
- std::vector< sp<RenderNode> > cards;
+ std::vector<sp<RenderNode> > cards;
void createContent(int width, int height, Canvas& canvas) override {
static SkColor COLORS[] = {
- 0xFFF44336,
- 0xFF9C27B0,
- 0xFF2196F3,
- 0xFF4CAF50,
+ 0xFFF44336, 0xFF9C27B0, 0xFF2196F3, 0xFF4CAF50,
};
canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
@@ -42,11 +38,11 @@ public:
for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
SkColor color = COLORS[static_cast<int>((y / dp(116))) % 4];
- sp<RenderNode> card = TestUtils::createNode(x, y,
- x + dp(100), y + dp(100),
- [color](RenderProperties& props, Canvas& canvas) {
- canvas.drawColor(color, SkBlendMode::kSrcOver);
- });
+ sp<RenderNode> card =
+ TestUtils::createNode(x, y, x + dp(100), y + dp(100),
+ [color](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(color, SkBlendMode::kSrcOver);
+ });
canvas.drawRenderNode(card.get());
cards.push_back(card);
}
@@ -59,8 +55,7 @@ public:
cards[0]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
TestUtils::recordNode(*cards[0], [curFrame](Canvas& canvas) {
- SkColor color = TestUtils::interpolateColor(
- curFrame / 150.0f, 0xFFF44336, 0xFFF8BBD0);
+ SkColor color = TestUtils::interpolateColor(curFrame / 150.0f, 0xFFF44336, 0xFFF8BBD0);
canvas.drawColor(color, SkBlendMode::kSrcOver);
});
}
diff --git a/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp b/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp
index bc6fc6452e90..1d17a021069b 100644
--- a/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp
+++ b/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp
@@ -19,10 +19,8 @@
class ReadbackFromHardware;
static TestScene::Registrar _SaveLayer(TestScene::Info{
- "readbackFromHBitmap",
- "Allocates hardware bitmap and readback data from it.",
- TestScene::simpleCreateScene<ReadbackFromHardware>
-});
+ "readbackFromHBitmap", "Allocates hardware bitmap and readback data from it.",
+ TestScene::simpleCreateScene<ReadbackFromHardware>});
class ReadbackFromHardware : public TestScene {
public:
@@ -41,7 +39,7 @@ public:
}
void createContent(int width, int height, Canvas& canvas) override {
- canvas.drawColor(Color::White, SkBlendMode::kSrcOver); // background
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver); // background
sk_sp<Bitmap> hardwareBitmap(createHardwareBitmap());
@@ -50,7 +48,7 @@ public:
SkBitmap canvasBitmap;
sk_sp<Bitmap> heapBitmap(TestUtils::createBitmap(hardwareBitmap->width(),
- hardwareBitmap->height(), &canvasBitmap));
+ hardwareBitmap->height(), &canvasBitmap));
SkCanvas skCanvas(canvasBitmap);
skCanvas.drawBitmap(readback, 0, 0);
@@ -59,5 +57,5 @@ public:
canvas.drawBitmap(*hardwareBitmap, 0, 500, nullptr);
}
- void doFrame(int frameNr) override { }
+ void doFrame(int frameNr) override {}
};
diff --git a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
index 825602466f92..3480a0f18407 100644
--- a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
@@ -20,20 +20,16 @@
class RecentsAnimation;
static TestScene::Registrar _Recents(TestScene::Info{
- "recents",
- "A recents-like scrolling list of textures. "
- "Consists of updating a texture every frame",
- TestScene::simpleCreateScene<RecentsAnimation>
-});
+ "recents",
+ "A recents-like scrolling list of textures. "
+ "Consists of updating a texture every frame",
+ TestScene::simpleCreateScene<RecentsAnimation>});
class RecentsAnimation : public TestScene {
public:
void createContent(int width, int height, Canvas& renderer) override {
static SkColor COLORS[] = {
- Color::Red_500,
- Color::Purple_500,
- Color::Blue_500,
- Color::Green_500,
+ Color::Red_500, Color::Purple_500, Color::Blue_500, Color::Green_500,
};
thumbnailSize = std::min(std::min(width, height) / 2, 720);
@@ -65,25 +61,26 @@ public:
mCards[ci]->mutateStagingProperties().setTranslationY(curFrame);
mCards[ci]->setPropertyFieldsDirty(RenderNode::Y);
}
- mThumbnail.eraseColor(TestUtils::interpolateColor(
- curFrame / 150.0f, Color::Green_500, Color::DeepOrange_500));
+ mThumbnail.eraseColor(TestUtils::interpolateColor(curFrame / 150.0f, Color::Green_500,
+ Color::DeepOrange_500));
}
private:
sp<RenderNode> createCard(int x, int y, int width, int height, Bitmap& thumb) {
- return TestUtils::createNode(x, y, x + width, y + height,
+ return TestUtils::createNode(
+ x, y, x + width, y + height,
[&thumb, width, height](RenderProperties& props, Canvas& canvas) {
- props.setElevation(dp(16));
- props.mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
- props.mutableOutline().setShouldClip(true);
+ props.setElevation(dp(16));
+ props.mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
+ props.mutableOutline().setShouldClip(true);
- canvas.drawColor(Color::Grey_200, SkBlendMode::kSrcOver);
- canvas.drawBitmap(thumb, 0, 0, thumb.width(), thumb.height(),
- 0, 0, width, height, nullptr);
- });
+ canvas.drawColor(Color::Grey_200, SkBlendMode::kSrcOver);
+ canvas.drawBitmap(thumb, 0, 0, thumb.width(), thumb.height(), 0, 0, width,
+ height, nullptr);
+ });
}
SkBitmap mThumbnail;
- std::vector< sp<RenderNode> > mCards;
+ std::vector<sp<RenderNode> > mCards;
int thumbnailSize;
};
diff --git a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
index 668eec69c2d0..6a3b6a57b28a 100644
--- a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-
#include "TestSceneBase.h"
class RectGridAnimation;
static TestScene::Registrar _RectGrid(TestScene::Info{
- "rectgrid",
- "A dense grid of 1x1 rects that should visually look like a single rect. "
- "Low CPU/GPU load.",
- TestScene::simpleCreateScene<RectGridAnimation>
-});
+ "rectgrid",
+ "A dense grid of 1x1 rects that should visually look like a single rect. "
+ "Low CPU/GPU load.",
+ TestScene::simpleCreateScene<RectGridAnimation>});
class RectGridAnimation : public TestScene {
public:
@@ -33,13 +31,12 @@ public:
canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
canvas.insertReorderBarrier(true);
- card = TestUtils::createNode(50, 50, 250, 250,
- [](RenderProperties& props, Canvas& canvas) {
+ card = TestUtils::createNode(50, 50, 250, 250, [](RenderProperties& props, Canvas& canvas) {
canvas.drawColor(0xFFFF00FF, SkBlendMode::kSrcOver);
SkRegion region;
- for (int xOffset = 0; xOffset < 200; xOffset+=2) {
- for (int yOffset = 0; yOffset < 200; yOffset+=2) {
+ for (int xOffset = 0; xOffset < 200; xOffset += 2) {
+ for (int yOffset = 0; yOffset < 200; yOffset += 2) {
region.op(xOffset, yOffset, xOffset + 1, yOffset + 1, SkRegion::kUnion_Op);
}
}
diff --git a/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp b/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
index 4b6632d244f5..314e922e9f38 100644
--- a/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
#include "TestSceneBase.h"
#include <vector>
@@ -23,10 +22,9 @@ class RoundRectClippingAnimation : public TestScene {
public:
int mSpacing, mSize;
- RoundRectClippingAnimation(int spacing, int size)
- : mSpacing(spacing), mSize(size) {}
+ RoundRectClippingAnimation(int spacing, int size) : mSpacing(spacing), mSize(size) {}
- std::vector< sp<RenderNode> > cards;
+ std::vector<sp<RenderNode> > cards;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
canvas.insertReorderBarrier(true);
@@ -35,13 +33,13 @@ public:
for (int x = 0; x < width; x += mSpacing) {
for (int y = 0; y < height; y += mSpacing) {
auto color = BrightColors[ci++ % BrightColorsCount];
- auto card = TestUtils::createNode(x, y, x + mSize, y + mSize,
- [&](RenderProperties& props, Canvas& canvas) {
- canvas.drawColor(color, SkBlendMode::kSrcOver);
- props.mutableOutline().setRoundRect(0, 0,
- props.getWidth(), props.getHeight(), mSize * .25, 1);
- props.mutableOutline().setShouldClip(true);
- });
+ auto card = TestUtils::createNode(
+ x, y, x + mSize, y + mSize, [&](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(color, SkBlendMode::kSrcOver);
+ props.mutableOutline().setRoundRect(0, 0, props.getWidth(),
+ props.getHeight(), mSize * .25, 1);
+ props.mutableOutline().setShouldClip(true);
+ });
canvas.drawRenderNode(card.get());
cards.push_back(card);
}
@@ -61,17 +59,15 @@ public:
};
static TestScene::Registrar _RoundRectClippingGpu(TestScene::Info{
- "roundRectClipping-gpu",
- "A bunch of RenderNodes with round rect clipping outlines that's GPU limited.",
- [](const TestScene::Options&) -> test::TestScene* {
- return new RoundRectClippingAnimation(dp(40), dp(200));
- }
-});
+ "roundRectClipping-gpu",
+ "A bunch of RenderNodes with round rect clipping outlines that's GPU limited.",
+ [](const TestScene::Options&) -> test::TestScene* {
+ return new RoundRectClippingAnimation(dp(40), dp(200));
+ }});
static TestScene::Registrar _RoundRectClippingCpu(TestScene::Info{
- "roundRectClipping-cpu",
- "A bunch of RenderNodes with round rect clipping outlines that's CPU limited.",
- [](const TestScene::Options&) -> test::TestScene* {
- return new RoundRectClippingAnimation(dp(20), dp(20));
- }
-});
+ "roundRectClipping-cpu",
+ "A bunch of RenderNodes with round rect clipping outlines that's CPU limited.",
+ [](const TestScene::Options&) -> test::TestScene* {
+ return new RoundRectClippingAnimation(dp(20), dp(20));
+ }});
diff --git a/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
index ad0b1f15abff..3befce4a395f 100644
--- a/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
@@ -14,19 +14,18 @@
* limitations under the License.
*/
-#include "TestSceneBase.h"
-#include <string>
#include <hwui/Paint.h>
#include <minikin/Layout.h>
+#include <string>
+#include "TestSceneBase.h"
class SaveLayer2Animation;
static TestScene::Registrar _SaveLayer(TestScene::Info{
- "savelayer2",
- "Interleaving 20 drawText/drawRect ops with saveLayer"
- "Tests the clipped saveLayer performance and FBO switching overhead.",
- TestScene::simpleCreateScene<SaveLayer2Animation>
-});
+ "savelayer2",
+ "Interleaving 20 drawText/drawRect ops with saveLayer"
+ "Tests the clipped saveLayer performance and FBO switching overhead.",
+ TestScene::simpleCreateScene<SaveLayer2Animation>});
class SaveLayer2Animation : public TestScene {
public:
@@ -37,7 +36,7 @@ public:
canvas.drawColor(SkColorSetARGB(255, 255, 0, 0), SkBlendMode::kSrcOver);
SkIRect bounds = SkIRect::MakeWH(width, height);
int regions = 20;
- int smallRectHeight = (bounds.height()/regions);
+ int smallRectHeight = (bounds.height() / regions);
int padding = smallRectHeight / 4;
int top = bounds.fTop;
@@ -46,27 +45,23 @@ public:
mGreenPaint.setColor(SkColorSetARGB(255, 0, 255, 0));
mGreenPaint.setTextSize(padding);
- //interleave drawText and drawRect with saveLayer ops
+ // interleave drawText and drawRect with saveLayer ops
for (int i = 0; i < regions; i++, top += smallRectHeight) {
- canvas.saveLayer(bounds.fLeft, top, bounds.fRight, top + padding,
- &mBluePaint, SaveFlags::ClipToLayer | SaveFlags::MatrixClip);
+ canvas.saveLayer(bounds.fLeft, top, bounds.fRight, top + padding, &mBluePaint,
+ SaveFlags::ClipToLayer | SaveFlags::MatrixClip);
canvas.drawColor(SkColorSetARGB(255, 255, 255, 0), SkBlendMode::kSrcOver);
std::string stri = std::to_string(i);
std::string offscreen = "offscreen line " + stri;
- std::unique_ptr<uint16_t[]> offtext = TestUtils::asciiToUtf16(offscreen.c_str());
- canvas.drawText(offtext.get(), 0, offscreen.length(), offscreen.length(),
- bounds.fLeft, top + padding, minikin::kBidi_Force_LTR, mBluePaint, nullptr);
+ TestUtils::drawUtf8ToCanvas(&canvas, offscreen.c_str(), mBluePaint, bounds.fLeft,
+ top + padding);
canvas.restore();
canvas.drawRect(bounds.fLeft, top + padding, bounds.fRight,
- top + smallRectHeight - padding, mBluePaint);
+ top + smallRectHeight - padding, mBluePaint);
std::string onscreen = "onscreen line " + stri;
- std::unique_ptr<uint16_t[]> ontext = TestUtils::asciiToUtf16(onscreen.c_str());
- canvas.drawText(ontext.get(), 0, onscreen.length(), onscreen.length(), bounds.fLeft,
- top + smallRectHeight - padding, minikin::kBidi_Force_LTR, mGreenPaint,
- nullptr);
+ TestUtils::drawUtf8ToCanvas(&canvas, onscreen.c_str(), mGreenPaint, bounds.fLeft,
+ top + smallRectHeight - padding);
}
}
- void doFrame(int frameNr) override {
- }
+ void doFrame(int frameNr) override {}
};
diff --git a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
index 7e8a7d9d14f2..02dd42ff2ae8 100644
--- a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
@@ -19,20 +19,19 @@
class SaveLayerAnimation;
static TestScene::Registrar _SaveLayer(TestScene::Info{
- "savelayer",
- "A nested pair of clipped saveLayer operations. "
- "Tests the clipped saveLayer codepath. Draws content into offscreen buffers and back again.",
- TestScene::simpleCreateScene<SaveLayerAnimation>
-});
+ "savelayer",
+ "A nested pair of clipped saveLayer operations. "
+ "Tests the clipped saveLayer codepath. Draws content into offscreen buffers and back "
+ "again.",
+ TestScene::simpleCreateScene<SaveLayerAnimation>});
class SaveLayerAnimation : public TestScene {
public:
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
- canvas.drawColor(Color::White, SkBlendMode::kSrcOver); // background
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver); // background
- card = TestUtils::createNode(0, 0, 400, 800,
- [](RenderProperties& props, Canvas& canvas) {
+ card = TestUtils::createNode(0, 0, 400, 800, [](RenderProperties& props, Canvas& canvas) {
// nested clipped saveLayers
canvas.saveLayerAlpha(0, 0, 400, 400, 200, SaveFlags::ClipToLayer);
canvas.drawColor(Color::Green_700, SkBlendMode::kSrcOver);
@@ -45,7 +44,7 @@ public:
// single unclipped saveLayer
canvas.save(SaveFlags::MatrixClip);
canvas.translate(0, 400);
- canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::Flags(0)); // unclipped
+ canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::Flags(0)); // unclipped
SkPaint paint;
paint.setAntiAlias(true);
paint.setColor(Color::Green_700);
diff --git a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
index 0a69b62fe615..bdc991ba1890 100644
--- a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
@@ -19,15 +19,14 @@
class ShadowGrid2Animation;
static TestScene::Registrar _ShadowGrid2(TestScene::Info{
- "shadowgrid2",
- "A dense grid of rounded rects that cast a shadow. This is a higher CPU load "
- "variant of shadowgrid. Very high CPU load, high GPU load.",
- TestScene::simpleCreateScene<ShadowGrid2Animation>
-});
+ "shadowgrid2",
+ "A dense grid of rounded rects that cast a shadow. This is a higher CPU load "
+ "variant of shadowgrid. Very high CPU load, high GPU load.",
+ TestScene::simpleCreateScene<ShadowGrid2Animation>});
class ShadowGrid2Animation : public TestScene {
public:
- std::vector< sp<RenderNode> > cards;
+ std::vector<sp<RenderNode> > cards;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
canvas.insertReorderBarrier(true);
@@ -50,14 +49,16 @@ public:
cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
}
+
private:
sp<RenderNode> createCard(int x, int y, int width, int height) {
return TestUtils::createNode(x, y, x + width, y + height,
- [width, height](RenderProperties& props, Canvas& canvas) {
- props.setElevation(dp(16));
- props.mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
- props.mutableOutline().setShouldClip(true);
- canvas.drawColor(0xFFEEEEEE, SkBlendMode::kSrcOver);
- });
+ [width, height](RenderProperties& props, Canvas& canvas) {
+ props.setElevation(dp(16));
+ props.mutableOutline().setRoundRect(0, 0, width, height,
+ dp(6), 1);
+ props.mutableOutline().setShouldClip(true);
+ canvas.drawColor(0xFFEEEEEE, SkBlendMode::kSrcOver);
+ });
}
};
diff --git a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
index 4a024295cb25..a12fd4d69280 100644
--- a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
@@ -19,15 +19,14 @@
class ShadowGridAnimation;
static TestScene::Registrar _ShadowGrid(TestScene::Info{
- "shadowgrid",
- "A grid of rounded rects that cast a shadow. Simplified scenario of an "
- "Android TV-style launcher interface. High CPU/GPU load.",
- TestScene::simpleCreateScene<ShadowGridAnimation>
-});
+ "shadowgrid",
+ "A grid of rounded rects that cast a shadow. Simplified scenario of an "
+ "Android TV-style launcher interface. High CPU/GPU load.",
+ TestScene::simpleCreateScene<ShadowGridAnimation>});
class ShadowGridAnimation : public TestScene {
public:
- std::vector< sp<RenderNode> > cards;
+ std::vector<sp<RenderNode> > cards;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
canvas.insertReorderBarrier(true);
@@ -50,14 +49,16 @@ public:
cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
}
+
private:
sp<RenderNode> createCard(int x, int y, int width, int height) {
return TestUtils::createNode(x, y, x + width, y + height,
- [width, height](RenderProperties& props, Canvas& canvas) {
- props.setElevation(dp(16));
- props.mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
- props.mutableOutline().setShouldClip(true);
- canvas.drawColor(0xFFEEEEEE, SkBlendMode::kSrcOver);
- });
+ [width, height](RenderProperties& props, Canvas& canvas) {
+ props.setElevation(dp(16));
+ props.mutableOutline().setRoundRect(0, 0, width, height,
+ dp(6), 1);
+ props.mutableOutline().setShouldClip(true);
+ canvas.drawColor(0xFFEEEEEE, SkBlendMode::kSrcOver);
+ });
}
};
diff --git a/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
index fac3968ff3d4..9f599100200e 100644
--- a/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
@@ -19,23 +19,22 @@
class ShadowShaderAnimation;
static TestScene::Registrar _ShadowShader(TestScene::Info{
- "shadowshader",
- "A set of overlapping shadowed areas with simple tessellation useful for"
- " benchmarking shadow shader performance.",
- TestScene::simpleCreateScene<ShadowShaderAnimation>
-});
+ "shadowshader",
+ "A set of overlapping shadowed areas with simple tessellation useful for"
+ " benchmarking shadow shader performance.",
+ TestScene::simpleCreateScene<ShadowShaderAnimation>});
class ShadowShaderAnimation : public TestScene {
public:
- std::vector< sp<RenderNode> > cards;
+ std::vector<sp<RenderNode> > cards;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
canvas.insertReorderBarrier(true);
int outset = 50;
for (int i = 0; i < 10; i++) {
- sp<RenderNode> card = createCard(outset, outset,
- width - (outset * 2), height - (outset * 2));
+ sp<RenderNode> card =
+ createCard(outset, outset, width - (outset * 2), height - (outset * 2));
canvas.drawRenderNode(card.get());
cards.push_back(card);
}
@@ -50,19 +49,24 @@ public:
cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
}
+
private:
sp<RenderNode> createCard(int x, int y, int width, int height) {
return TestUtils::createNode(x, y, x + width, y + height,
- [width, height](RenderProperties& props, Canvas& canvas) {
- props.setElevation(1000);
+ [width, height](RenderProperties& props, Canvas& canvas) {
+ props.setElevation(1000);
- // Set 0 radius, no clipping, so shadow is easy to compute. Slightly transparent outline
- // to signal contents aren't opaque (not necessary though, as elevation is so high, no
- // inner content to cut out)
- props.mutableOutline().setRoundRect(0, 0, width, height, 0, 0.99f);
- props.mutableOutline().setShouldClip(false);
+ // Set 0 radius, no clipping, so shadow is easy to compute.
+ // Slightly transparent outline
+ // to signal contents aren't opaque (not necessary though,
+ // as elevation is so high, no
+ // inner content to cut out)
+ props.mutableOutline().setRoundRect(0, 0, width, height, 0,
+ 0.99f);
+ props.mutableOutline().setShouldClip(false);
- // don't draw anything to card's canvas - we just want the shadow
- });
+ // don't draw anything to card's canvas - we just want the
+ // shadow
+ });
}
};
diff --git a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
index 09e70ebf7b5f..0d87776e083e 100644
--- a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
@@ -21,79 +21,75 @@
class ShapeAnimation;
-static TestScene::Registrar _Shapes(TestScene::Info{
- "shapes",
- "A grid of shape drawing test cases.",
- TestScene::simpleCreateScene<ShapeAnimation>
-});
+static TestScene::Registrar _Shapes(TestScene::Info{"shapes", "A grid of shape drawing test cases.",
+ TestScene::simpleCreateScene<ShapeAnimation>});
class ShapeAnimation : public TestScene {
public:
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
- card = TestUtils::createNode(0, 0, width, height,
- [width](RenderProperties& props, Canvas& canvas) {
- std::function<void(Canvas&, float, const SkPaint&)> ops[] = {
- [](Canvas& canvas, float size, const SkPaint& paint) {
- canvas.drawArc(0, 0, size, size, 50, 189, true, paint);
- },
- [](Canvas& canvas, float size, const SkPaint& paint) {
- canvas.drawOval(0, 0, size, size, paint);
- },
- [](Canvas& canvas, float size, const SkPaint& paint) {
- SkPath diamondPath;
- diamondPath.moveTo(size / 2, 0);
- diamondPath.lineTo(size, size / 2);
- diamondPath.lineTo(size / 2, size);
- diamondPath.lineTo(0, size / 2);
- diamondPath.close();
- canvas.drawPath(diamondPath, paint);
- },
- [](Canvas& canvas, float size, const SkPaint& paint) {
- float data[] = {0, 0, size, size, 0, size, size, 0 };
- canvas.drawLines(data, sizeof(data) / sizeof(float), paint);
- },
- [](Canvas& canvas, float size, const SkPaint& paint) {
- float data[] = {0, 0, size, size, 0, size, size, 0 };
- canvas.drawPoints(data, sizeof(data) / sizeof(float), paint);
- },
- [](Canvas& canvas, float size, const SkPaint& paint) {
- canvas.drawRect(0, 0, size, size, paint);
- },
- [](Canvas& canvas, float size, const SkPaint& paint) {
- float rad = size / 4;
- canvas.drawRoundRect(0, 0, size, size, rad, rad, paint);
- }
- };
- float cellSpace = dp(4);
- float cellSize = floorf(width / 7 - cellSpace);
+ card = TestUtils::createNode(
+ 0, 0, width, height, [width](RenderProperties& props, Canvas& canvas) {
+ std::function<void(Canvas&, float, const SkPaint&)> ops[] = {
+ [](Canvas& canvas, float size, const SkPaint& paint) {
+ canvas.drawArc(0, 0, size, size, 50, 189, true, paint);
+ },
+ [](Canvas& canvas, float size, const SkPaint& paint) {
+ canvas.drawOval(0, 0, size, size, paint);
+ },
+ [](Canvas& canvas, float size, const SkPaint& paint) {
+ SkPath diamondPath;
+ diamondPath.moveTo(size / 2, 0);
+ diamondPath.lineTo(size, size / 2);
+ diamondPath.lineTo(size / 2, size);
+ diamondPath.lineTo(0, size / 2);
+ diamondPath.close();
+ canvas.drawPath(diamondPath, paint);
+ },
+ [](Canvas& canvas, float size, const SkPaint& paint) {
+ float data[] = {0, 0, size, size, 0, size, size, 0};
+ canvas.drawLines(data, sizeof(data) / sizeof(float), paint);
+ },
+ [](Canvas& canvas, float size, const SkPaint& paint) {
+ float data[] = {0, 0, size, size, 0, size, size, 0};
+ canvas.drawPoints(data, sizeof(data) / sizeof(float), paint);
+ },
+ [](Canvas& canvas, float size, const SkPaint& paint) {
+ canvas.drawRect(0, 0, size, size, paint);
+ },
+ [](Canvas& canvas, float size, const SkPaint& paint) {
+ float rad = size / 4;
+ canvas.drawRoundRect(0, 0, size, size, rad, rad, paint);
+ }};
+ float cellSpace = dp(4);
+ float cellSize = floorf(width / 7 - cellSpace);
- // each combination of strokeWidth + style gets a column
- int outerCount = canvas.save(SaveFlags::MatrixClip);
- SkPaint paint;
- paint.setAntiAlias(true);
- SkPaint::Style styles[] = {
- SkPaint::kStroke_Style, SkPaint::kFill_Style, SkPaint::kStrokeAndFill_Style };
- for (auto style : styles) {
- paint.setStyle(style);
- for (auto strokeWidth : { 0.0f, 0.5f, 8.0f }) {
- paint.setStrokeWidth(strokeWidth);
- // fill column with each op
- int middleCount = canvas.save(SaveFlags::MatrixClip);
- for (auto op : ops) {
- int innerCount = canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(0, 0, cellSize, cellSize, SkClipOp::kIntersect);
- canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
- op(canvas, cellSize, paint);
- canvas.restoreToCount(innerCount);
- canvas.translate(cellSize + cellSpace, 0);
+ // each combination of strokeWidth + style gets a column
+ int outerCount = canvas.save(SaveFlags::MatrixClip);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkPaint::Style styles[] = {SkPaint::kStroke_Style, SkPaint::kFill_Style,
+ SkPaint::kStrokeAndFill_Style};
+ for (auto style : styles) {
+ paint.setStyle(style);
+ for (auto strokeWidth : {0.0f, 0.5f, 8.0f}) {
+ paint.setStrokeWidth(strokeWidth);
+ // fill column with each op
+ int middleCount = canvas.save(SaveFlags::MatrixClip);
+ for (auto op : ops) {
+ int innerCount = canvas.save(SaveFlags::MatrixClip);
+ canvas.clipRect(0, 0, cellSize, cellSize, SkClipOp::kIntersect);
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+ op(canvas, cellSize, paint);
+ canvas.restoreToCount(innerCount);
+ canvas.translate(cellSize + cellSpace, 0);
+ }
+ canvas.restoreToCount(middleCount);
+ canvas.translate(0, cellSize + cellSpace);
+ }
}
- canvas.restoreToCount(middleCount);
- canvas.translate(0, cellSize + cellSpace);
- }
- }
- canvas.restoreToCount(outerCount);
- });
+ canvas.restoreToCount(outerCount);
+ });
canvas.drawColor(Color::Grey_500, SkBlendMode::kSrcOver);
canvas.drawRenderNode(card.get());
}
diff --git a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
index a63a5852a9ff..ff0cb3705cb8 100644
--- a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
@@ -22,15 +22,15 @@
class SimpleColorMatrixAnimation;
static TestScene::Registrar _SimpleColorMatrix(TestScene::Info{
- "simpleColorMatrix",
- "A color matrix shader benchmark for the simple scale/translate case, which has R, G, and B "
- "all scaled and translated the same amount.",
- TestScene::simpleCreateScene<SimpleColorMatrixAnimation>
-});
+ "simpleColorMatrix",
+ "A color matrix shader benchmark for the simple scale/translate case, which has R, G, and "
+ "B "
+ "all scaled and translated the same amount.",
+ TestScene::simpleCreateScene<SimpleColorMatrixAnimation>});
class SimpleColorMatrixAnimation : public TestScene {
public:
- std::vector< sp<RenderNode> > cards;
+ std::vector<sp<RenderNode> > cards;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
@@ -46,38 +46,41 @@ public:
cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
}
+
private:
sp<RenderNode> createCard(int x, int y, int width, int height) {
- return TestUtils::createNode(x, y, x + width, y + height,
+ return TestUtils::createNode(
+ x, y, x + width, y + height,
[width, height](RenderProperties& props, Canvas& canvas) {
- SkPaint paint;
- float matrix[20] = { 0 };
+ SkPaint paint;
+ float matrix[20] = {0};
- // Simple scale/translate case where R, G, and B are all treated equivalently
- matrix[SkColorMatrix::kR_Scale] = 1.1f;
- matrix[SkColorMatrix::kG_Scale] = 1.1f;
- matrix[SkColorMatrix::kB_Scale] = 1.1f;
- matrix[SkColorMatrix::kA_Scale] = 0.5f;
+ // Simple scale/translate case where R, G, and B are all treated equivalently
+ matrix[SkColorMatrix::kR_Scale] = 1.1f;
+ matrix[SkColorMatrix::kG_Scale] = 1.1f;
+ matrix[SkColorMatrix::kB_Scale] = 1.1f;
+ matrix[SkColorMatrix::kA_Scale] = 0.5f;
- matrix[SkColorMatrix::kR_Trans] = 5.0f;
- matrix[SkColorMatrix::kG_Trans] = 5.0f;
- matrix[SkColorMatrix::kB_Trans] = 5.0f;
- matrix[SkColorMatrix::kA_Trans] = 10.0f;
+ matrix[SkColorMatrix::kR_Trans] = 5.0f;
+ matrix[SkColorMatrix::kG_Trans] = 5.0f;
+ matrix[SkColorMatrix::kB_Trans] = 5.0f;
+ matrix[SkColorMatrix::kA_Trans] = 10.0f;
- paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
+ paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
- // set a shader so it's not likely for the matrix to be optimized away (since a clever
- // enough renderer might apply it directly to the paint color)
- float pos[] = { 0, 1 };
- SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(width, height) };
- SkColor colors[2] = { Color::DeepPurple_500, Color::DeepOrange_500 };
- paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2,
- SkShader::kClamp_TileMode));
+ // set a shader so it's not likely for the matrix to be optimized away (since a
+ // clever
+ // enough renderer might apply it directly to the paint color)
+ float pos[] = {0, 1};
+ SkPoint pts[] = {SkPoint::Make(0, 0), SkPoint::Make(width, height)};
+ SkColor colors[2] = {Color::DeepPurple_500, Color::DeepOrange_500};
+ paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2,
+ SkShader::kClamp_TileMode));
- // overdraw several times to emphasize shader cost
- for (int i = 0; i < 10; i++) {
- canvas.drawRect(i, i, width, height, paint);
- }
- });
+ // overdraw several times to emphasize shader cost
+ for (int i = 0; i < 10; i++) {
+ canvas.drawRect(i, i, width, height, paint);
+ }
+ });
}
};
diff --git a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
index 053eb6dee31c..016c65c17c4c 100644
--- a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
#include "TestSceneBase.h"
#include <SkGradientShader.h>
@@ -22,14 +21,13 @@
class SimpleGradientAnimation;
static TestScene::Registrar _SimpleGradient(TestScene::Info{
- "simpleGradient",
- "A benchmark of shader performance of linear, 2 color gradients with black in them.",
- TestScene::simpleCreateScene<SimpleGradientAnimation>
-});
+ "simpleGradient",
+ "A benchmark of shader performance of linear, 2 color gradients with black in them.",
+ TestScene::simpleCreateScene<SimpleGradientAnimation>});
class SimpleGradientAnimation : public TestScene {
public:
- std::vector< sp<RenderNode> > cards;
+ std::vector<sp<RenderNode> > cards;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
@@ -45,21 +43,23 @@ public:
cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
}
+
private:
sp<RenderNode> createCard(int x, int y, int width, int height) {
- return TestUtils::createNode(x, y, x + width, y + height,
+ return TestUtils::createNode(
+ x, y, x + width, y + height,
[width, height](RenderProperties& props, Canvas& canvas) {
- float pos[] = { 0, 1 };
- SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(width, height) };
- SkPaint paint;
- // overdraw several times to emphasize shader cost
- for (int i = 0; i < 10; i++) {
- // use i%2 start position to pick 2 color combo with black in it
- SkColor colors[3] = { Color::Transparent, Color::Black, Color::Cyan_500 };
- paint.setShader(SkGradientShader::MakeLinear(pts, colors + (i % 2), pos, 2,
- SkShader::kClamp_TileMode));
- canvas.drawRect(i, i, width, height, paint);
- }
- });
+ float pos[] = {0, 1};
+ SkPoint pts[] = {SkPoint::Make(0, 0), SkPoint::Make(width, height)};
+ SkPaint paint;
+ // overdraw several times to emphasize shader cost
+ for (int i = 0; i < 10; i++) {
+ // use i%2 start position to pick 2 color combo with black in it
+ SkColor colors[3] = {Color::Transparent, Color::Black, Color::Cyan_500};
+ paint.setShader(SkGradientShader::MakeLinear(pts, colors + (i % 2), pos, 2,
+ SkShader::kClamp_TileMode));
+ canvas.drawRect(i, i, width, height, paint);
+ }
+ });
}
};
diff --git a/libs/hwui/tests/common/scenes/TextAnimation.cpp b/libs/hwui/tests/common/scenes/TextAnimation.cpp
index 438f877deb3e..a16b17849fc6 100644
--- a/libs/hwui/tests/common/scenes/TextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/TextAnimation.cpp
@@ -15,25 +15,20 @@
*/
#include "TestSceneBase.h"
-#include "utils/Color.h"
class TextAnimation;
-static TestScene::Registrar _Text(TestScene::Info{
- "text",
- "Draws a bunch of text.",
- TestScene::simpleCreateScene<TextAnimation>
-});
+static TestScene::Registrar _Text(TestScene::Info{"text", "Draws a bunch of text.",
+ TestScene::simpleCreateScene<TextAnimation>});
class TextAnimation : public TestScene {
public:
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
- card = TestUtils::createNode(0, 0, width, height,
- [](RenderProperties& props, Canvas& canvas) {
+ card = TestUtils::createNode(0, 0, width, height, [](RenderProperties& props,
+ Canvas& canvas) {
SkPaint paint;
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setAntiAlias(true);
paint.setTextSize(50);
diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp
index 04fc2d46f946..a64e8444a9b1 100644
--- a/libs/hwui/tests/common/scenes/TvApp.cpp
+++ b/libs/hwui/tests/common/scenes/TvApp.cpp
@@ -14,40 +14,42 @@
* limitations under the License.
*/
+#include "SkBlendMode.h"
#include "TestSceneBase.h"
#include "tests/common/BitmapAllocationTestUtils.h"
-#include "SkBlendMode.h"
class TvApp;
class TvAppNoRoundedCorner;
class TvAppColorFilter;
class TvAppNoRoundedCornerColorFilter;
-static bool _TvApp(
- BitmapAllocationTestUtils::registerBitmapAllocationScene<TvApp>(
- "tvapp", "A dense grid of cards:"
- "with rounded corner, using overlay RenderNode for dimming."));
+static bool _TvApp(BitmapAllocationTestUtils::registerBitmapAllocationScene<TvApp>(
+ "tvapp",
+ "A dense grid of cards:"
+ "with rounded corner, using overlay RenderNode for dimming."));
static bool _TvAppNoRoundedCorner(
BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCorner>(
- "tvapp_norc", "A dense grid of cards:"
+ "tvapp_norc",
+ "A dense grid of cards:"
"no rounded corner, using overlay RenderNode for dimming"));
static bool _TvAppColorFilter(
BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppColorFilter>(
- "tvapp_cf", "A dense grid of cards:"
+ "tvapp_cf",
+ "A dense grid of cards:"
"with rounded corner, using ColorFilter for dimming"));
static bool _TvAppNoRoundedCornerColorFilter(
BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCornerColorFilter>(
- "tvapp_norc_cf", "A dense grid of cards:"
+ "tvapp_norc_cf",
+ "A dense grid of cards:"
"no rounded corner, using ColorFilter for dimming"));
class TvApp : public TestScene {
public:
TvApp(BitmapAllocationTestUtils::BitmapAllocator allocator)
- : TestScene()
- , mAllocator(allocator) { }
+ : TestScene(), mAllocator(allocator) {}
sp<RenderNode> mBg;
std::vector<sp<RenderNode>> mCards;
@@ -66,9 +68,7 @@ public:
canvas.insertReorderBarrier(true);
mSingleBitmap = mAllocator(dp(160), dp(120), kRGBA_8888_SkColorType,
- [](SkBitmap& skBitmap) {
- skBitmap.eraseColor(0xFF0000FF);
- });
+ [](SkBitmap& skBitmap) { skBitmap.eraseColor(0xFF0000FF); });
for (int y = dp(18) - dp(178); y < height - dp(18); y += dp(178)) {
bool isFirstCard = true;
@@ -90,69 +90,63 @@ public:
}
private:
- sp<RenderNode> createBitmapNode(Canvas& canvas, SkColor color, int left, int top,
- int width, int height) {
- return TestUtils::createNode(left, top, left + width , top + height,
+ sp<RenderNode> createBitmapNode(Canvas& canvas, SkColor color, int left, int top, int width,
+ int height) {
+ return TestUtils::createNode(
+ left, top, left + width, top + height,
[this, width, height, color](RenderProperties& props, Canvas& canvas) {
- sk_sp<Bitmap> bitmap = mAllocator(width, height, kRGBA_8888_SkColorType,
- [color](SkBitmap& skBitmap) {
- skBitmap.eraseColor(color);
- });
- canvas.drawBitmap(*bitmap, 0, 0, nullptr);
- });
+ sk_sp<Bitmap> bitmap =
+ mAllocator(width, height, kRGBA_8888_SkColorType,
+ [color](SkBitmap& skBitmap) { skBitmap.eraseColor(color); });
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ });
}
- sp<RenderNode> createSharedBitmapNode(Canvas& canvas, int left, int top,
- int width, int height, sk_sp<Bitmap>bitmap) {
- return TestUtils::createNode(left, top, left + width , top + height,
- [bitmap](RenderProperties& props, Canvas& canvas) {
- canvas.drawBitmap(*bitmap, 0, 0, nullptr);
- });
+ sp<RenderNode> createSharedBitmapNode(Canvas& canvas, int left, int top, int width, int height,
+ sk_sp<Bitmap> bitmap) {
+ return TestUtils::createNode(left, top, left + width, top + height,
+ [bitmap](RenderProperties& props, Canvas& canvas) {
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ });
}
- sp<RenderNode> createInfoNode(Canvas& canvas, int left, int top,
- int width, int height, const char* text, const char* text2) {
- return TestUtils::createNode(left, top, left + width , top + height,
- [text, text2](RenderProperties& props, Canvas& canvas) {
- canvas.drawColor(0xFFFFEEEE, SkBlendMode::kSrcOver);
+ sp<RenderNode> createInfoNode(Canvas& canvas, int left, int top, int width, int height,
+ const char* text, const char* text2) {
+ return TestUtils::createNode(left, top, left + width, top + height,
+ [text, text2](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(0xFFFFEEEE, SkBlendMode::kSrcOver);
- SkPaint paint;
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- paint.setAntiAlias(true);
- paint.setTextSize(24);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(24);
- paint.setColor(Color::Black);
- TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 10, 30);
- paint.setTextSize(20);
- TestUtils::drawUtf8ToCanvas(&canvas, text2, paint, 10, 54);
+ paint.setColor(Color::Black);
+ TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 10, 30);
+ paint.setTextSize(20);
+ TestUtils::drawUtf8ToCanvas(&canvas, text2, paint, 10, 54);
- });
+ });
}
- sp<RenderNode> createColorNode(Canvas& canvas, int left, int top,
- int width, int height, SkColor color) {
- return TestUtils::createNode(left, top, left + width , top + height,
- [color](RenderProperties& props, Canvas& canvas) {
- canvas.drawColor(color, SkBlendMode::kSrcOver);
- });
+ sp<RenderNode> createColorNode(Canvas& canvas, int left, int top, int width, int height,
+ SkColor color) {
+ return TestUtils::createNode(left, top, left + width, top + height,
+ [color](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(color, SkBlendMode::kSrcOver);
+ });
}
- virtual bool useSingleBitmap() {
- return false;
- }
+ virtual bool useSingleBitmap() { return false; }
- virtual float roundedCornerRadius() {
- return dp(2);
- }
+ virtual float roundedCornerRadius() { return dp(2); }
// when true, use overlay RenderNode for dimming, otherwise apply a ColorFilter to dim image
- virtual bool useOverlay() {
- return true;
- }
+ virtual bool useOverlay() { return true; }
sp<RenderNode> createCard(int x, int y, int width, int height, bool selected) {
- return TestUtils::createNode(x, y, x + width, y + height,
- [width, height, selected, this](RenderProperties& props, Canvas& canvas) {
+ return TestUtils::createNode(x, y, x + width, y + height, [width, height, selected, this](
+ RenderProperties& props,
+ Canvas& canvas) {
if (selected) {
props.setElevation(dp(16));
props.setScaleX(1.2);
@@ -161,12 +155,14 @@ private:
props.mutableOutline().setRoundRect(0, 0, width, height, roundedCornerRadius(), 1);
props.mutableOutline().setShouldClip(true);
- sk_sp<Bitmap> bitmap = useSingleBitmap() ? mSingleBitmap
- : mAllocator(width, dp(120), kRGBA_8888_SkColorType, [this](SkBitmap& skBitmap) {
- skBitmap.eraseColor(0xFF000000 | ((mSeed << 3) & 0xFF));
- });
- sp<RenderNode> cardImage = createSharedBitmapNode(canvas, 0, 0, width, dp(120),
- bitmap);
+ sk_sp<Bitmap> bitmap =
+ useSingleBitmap() ? mSingleBitmap
+ : mAllocator(width, dp(120), kRGBA_8888_SkColorType,
+ [this](SkBitmap& skBitmap) {
+ skBitmap.eraseColor(0xFF000000 |
+ ((mSeed << 3) & 0xFF));
+ });
+ sp<RenderNode> cardImage = createSharedBitmapNode(canvas, 0, 0, width, dp(120), bitmap);
canvas.drawRenderNode(cardImage.get());
mCachedBitmaps.push_back(bitmap);
mImages.push_back(cardImage);
@@ -176,12 +172,14 @@ private:
mSeed++;
char buffer2[128];
sprintf(buffer2, "Studio %d", mSeed2++);
- sp<RenderNode> infoArea = createInfoNode(canvas, 0, dp(120), width, height, buffer, buffer2);
+ sp<RenderNode> infoArea =
+ createInfoNode(canvas, 0, dp(120), width, height, buffer, buffer2);
canvas.drawRenderNode(infoArea.get());
mInfoAreas.push_back(infoArea);
if (useOverlay()) {
- sp<RenderNode> overlayColor = createColorNode(canvas, 0, 0, width, height, 0x00000000);
+ sp<RenderNode> overlayColor =
+ createColorNode(canvas, 0, 0, width, height, 0x00000000);
canvas.drawRenderNode(overlayColor.get());
mOverlays.push_back(overlayColor);
}
@@ -196,30 +194,31 @@ private:
// re-recording card's canvas, not necessary but to add some burden to CPU
std::unique_ptr<Canvas> cardcanvas(Canvas::create_recording_canvas(
- card->stagingProperties().getWidth(),
- card->stagingProperties().getHeight()));
+ card->stagingProperties().getWidth(), card->stagingProperties().getHeight(),
+ card.get()));
sp<RenderNode> image = mImages[ci];
sp<RenderNode> infoArea = mInfoAreas[ci];
cardcanvas->drawRenderNode(infoArea.get());
if (useOverlay()) {
- cardcanvas->drawRenderNode(image.get());
+ cardcanvas->drawRenderNode(image.get());
// re-recording card overlay's canvas, animating overlay color alpha
sp<RenderNode> overlay = mOverlays[ci];
- std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- overlay->stagingProperties().getWidth(),
- overlay->stagingProperties().getHeight()));
+ std::unique_ptr<Canvas> canvas(
+ Canvas::create_recording_canvas(overlay->stagingProperties().getWidth(),
+ overlay->stagingProperties().getHeight(),
+ overlay.get()));
canvas->drawColor((curFrame % 150) << 24, SkBlendMode::kSrcOver);
overlay->setStagingDisplayList(canvas->finishRecording());
cardcanvas->drawRenderNode(overlay.get());
} else {
// re-recording image node's canvas, animating ColorFilter
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- image->stagingProperties().getWidth(),
- image->stagingProperties().getHeight()));
+ image->stagingProperties().getWidth(), image->stagingProperties().getHeight(),
+ image.get()));
SkPaint paint;
- sk_sp<SkColorFilter> filter(SkColorFilter::MakeModeFilter((curFrame % 150) << 24,
- SkBlendMode::kSrcATop));
+ sk_sp<SkColorFilter> filter(
+ SkColorFilter::MakeModeFilter((curFrame % 150) << 24, SkBlendMode::kSrcATop));
paint.setColorFilter(filter);
sk_sp<Bitmap> bitmap = mCachedBitmaps[ci];
canvas->drawBitmap(*bitmap, 0, 0, &paint);
@@ -233,42 +232,27 @@ private:
class TvAppNoRoundedCorner : public TvApp {
public:
- TvAppNoRoundedCorner(BitmapAllocationTestUtils::BitmapAllocator allocator)
- : TvApp(allocator) { }
+ TvAppNoRoundedCorner(BitmapAllocationTestUtils::BitmapAllocator allocator) : TvApp(allocator) {}
private:
-
- virtual float roundedCornerRadius() override {
- return dp(0);
- }
+ virtual float roundedCornerRadius() override { return dp(0); }
};
class TvAppColorFilter : public TvApp {
public:
- TvAppColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator)
- : TvApp(allocator) { }
+ TvAppColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator) : TvApp(allocator) {}
private:
-
- virtual bool useOverlay() override {
- return false;
- }
+ virtual bool useOverlay() override { return false; }
};
class TvAppNoRoundedCornerColorFilter : public TvApp {
public:
TvAppNoRoundedCornerColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator)
- : TvApp(allocator) { }
+ : TvApp(allocator) {}
private:
+ virtual float roundedCornerRadius() override { return dp(0); }
- virtual float roundedCornerRadius() override {
- return dp(0);
- }
-
- virtual bool useOverlay() override {
- return false;
- }
+ virtual bool useOverlay() override { return false; }
};
-
-
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index f8d63978bb53..9428f532434a 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -16,11 +16,11 @@
#include "AnimationContext.h"
#include "RenderNode.h"
+#include "renderthread/RenderProxy.h"
+#include "renderthread/RenderTask.h"
#include "tests/common/TestContext.h"
#include "tests/common/TestScene.h"
#include "tests/common/scenes/TestSceneBase.h"
-#include "renderthread/RenderProxy.h"
-#include "renderthread/RenderTask.h"
#include <benchmark/benchmark.h>
#include <gui/Surface.h>
@@ -39,7 +39,7 @@ public:
}
};
-template<class T>
+template <class T>
class ModifiedMovingAverage {
public:
explicit ModifiedMovingAverage(int weight) : mWeight(weight) {}
@@ -53,9 +53,7 @@ public:
return mAverage;
}
- T average() {
- return mAverage;
- }
+ T average() { return mAverage; }
private:
bool mHasValue = false;
@@ -64,8 +62,8 @@ private:
};
void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options& opts,
- benchmark::BenchmarkReporter* reporter, RenderProxy* proxy,
- double durationInS) {
+ benchmark::BenchmarkReporter* reporter, RenderProxy* proxy,
+ double durationInS) {
using namespace benchmark;
struct ReportInfo {
@@ -74,10 +72,8 @@ void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options
};
static std::array<ReportInfo, 4> REPORTS = {
- ReportInfo { 50, "_50th" },
- ReportInfo { 90, "_90th" },
- ReportInfo { 95, "_95th" },
- ReportInfo { 99, "_99th" },
+ ReportInfo{50, "_50th"}, ReportInfo{90, "_90th"}, ReportInfo{95, "_95th"},
+ ReportInfo{99, "_99th"},
};
// Although a vector is used, it must stay with only a single element
@@ -111,12 +107,10 @@ void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options
}
void run(const TestScene::Info& info, const TestScene::Options& opts,
- benchmark::BenchmarkReporter* reporter) {
+ benchmark::BenchmarkReporter* reporter) {
// Switch to the real display
gDisplay = getBuiltInDisplay();
- std::unique_ptr<TestScene> scene(info.createScene(opts));
-
Properties::forceDrawFrame = true;
TestContext testContext;
testContext.setRenderOffscreen(opts.renderOffscreen);
@@ -126,15 +120,17 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
const int height = gDisplay.h;
sp<Surface> surface = testContext.surface();
- sp<RenderNode> rootNode = TestUtils::createNode(0, 0, width, height,
- [&scene, width, height](RenderProperties& props, Canvas& canvas) {
- props.setClipToBounds(false);
- scene->createContent(width, height, canvas);
- });
+ std::unique_ptr<TestScene> scene(info.createScene(opts));
+ scene->renderTarget = surface;
+
+ sp<RenderNode> rootNode = TestUtils::createNode(
+ 0, 0, width, height, [&scene, width, height](RenderProperties& props, Canvas& canvas) {
+ props.setClipToBounds(false);
+ scene->createContent(width, height, canvas);
+ });
ContextFactory factory;
- std::unique_ptr<RenderProxy> proxy(new RenderProxy(false,
- rootNode.get(), &factory));
+ std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode.get(), &factory));
proxy->loadSystemProperties();
proxy->initialize(surface);
float lightX = width / 2.0;
@@ -182,8 +178,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
nsecs_t end = systemTime(CLOCK_MONOTONIC);
if (reporter) {
- outputBenchmarkReport(info, opts, reporter, proxy.get(),
- (end - start) / (double) s2ns(1));
+ outputBenchmarkReport(info, opts, reporter, proxy.get(), (end - start) / (double)s2ns(1));
} else {
proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
}
diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp
index 648fd35d787c..853360666f3d 100644
--- a/libs/hwui/tests/macrobench/main.cpp
+++ b/libs/hwui/tests/macrobench/main.cpp
@@ -45,7 +45,7 @@ static TestScene::Options gOpts;
std::unique_ptr<benchmark::BenchmarkReporter> gBenchmarkReporter;
void run(const TestScene::Info& info, const TestScene::Options& opts,
- benchmark::BenchmarkReporter* reporter);
+ benchmark::BenchmarkReporter* reporter);
static void printHelp() {
printf(R"(
@@ -67,6 +67,7 @@ OPTIONS:
--onscreen Render tests on device screen. By default tests
are offscreen rendered
--benchmark_format Set output format. Possible values are tabular, json, csv
+ --renderer=TYPE Sets the render pipeline to use. May be opengl, skiagl, or skiavk
)");
}
@@ -81,7 +82,7 @@ static void listTests() {
do {
int toPrint = dlen;
if (toPrint > 50) {
- char* found = (char*) memrchr(col2, ' ', 50);
+ char* found = (char*)memrchr(col2, ' ', 50);
if (found) {
toPrint = found - col2;
} else {
@@ -93,7 +94,8 @@ static void listTests() {
col2 += toPrint;
dlen -= toPrint;
while (*col2 == ' ') {
- col2++; dlen--;
+ col2++;
+ dlen--;
}
} while (dlen > 0);
printf("\n");
@@ -119,7 +121,7 @@ static void moveToCpuSet(const char* cpusetName) {
}
pid_t pid = getpid();
- int towrite = snprintf(buffer, BUF_SIZE, "%ld", (long) pid);
+ int towrite = snprintf(buffer, BUF_SIZE, "%ld", (long)pid);
if (towrite >= BUF_SIZE) {
fprintf(stderr, "Buffer wasn't large enough?\n");
} else {
@@ -142,6 +144,20 @@ static bool setBenchmarkFormat(const char* format) {
return true;
}
+static bool setRenderer(const char* renderer) {
+ if (!strcmp(renderer, "opengl")) {
+ Properties::overrideRenderPipelineType(RenderPipelineType::OpenGL);
+ } else if (!strcmp(renderer, "skiagl")) {
+ Properties::overrideRenderPipelineType(RenderPipelineType::SkiaGL);
+ } else if (!strcmp(renderer, "skiavk")) {
+ Properties::overrideRenderPipelineType(RenderPipelineType::SkiaVulkan);
+ } else {
+ fprintf(stderr, "Unknown format '%s'", renderer);
+ return false;
+ }
+ return true;
+}
+
// For options that only exist in long-form. Anything in the
// 0-255 range is reserved for short options (which just use their ASCII value)
namespace LongOpts {
@@ -154,22 +170,23 @@ enum {
BenchmarkFormat,
Onscreen,
Offscreen,
+ Renderer,
};
}
static const struct option LONG_OPTIONS[] = {
- { "frames", required_argument, nullptr, 'f' },
- { "repeat", required_argument, nullptr, 'r' },
- { "help", no_argument, nullptr, 'h' },
- { "list", no_argument, nullptr, LongOpts::List },
- { "wait-for-gpu", no_argument, nullptr, LongOpts::WaitForGpu },
- { "report-frametime", optional_argument, nullptr, LongOpts::ReportFrametime },
- { "cpuset", required_argument, nullptr, LongOpts::CpuSet },
- { "benchmark_format", required_argument, nullptr, LongOpts::BenchmarkFormat },
- { "onscreen", no_argument, nullptr, LongOpts::Onscreen },
- { "offscreen", no_argument, nullptr, LongOpts::Offscreen },
- { 0, 0, 0, 0 }
-};
+ {"frames", required_argument, nullptr, 'f'},
+ {"repeat", required_argument, nullptr, 'r'},
+ {"help", no_argument, nullptr, 'h'},
+ {"list", no_argument, nullptr, LongOpts::List},
+ {"wait-for-gpu", no_argument, nullptr, LongOpts::WaitForGpu},
+ {"report-frametime", optional_argument, nullptr, LongOpts::ReportFrametime},
+ {"cpuset", required_argument, nullptr, LongOpts::CpuSet},
+ {"benchmark_format", required_argument, nullptr, LongOpts::BenchmarkFormat},
+ {"onscreen", no_argument, nullptr, LongOpts::Onscreen},
+ {"offscreen", no_argument, nullptr, LongOpts::Offscreen},
+ {"renderer", required_argument, nullptr, LongOpts::Renderer},
+ {0, 0, 0, 0}};
static const char* SHORT_OPTIONS = "c:r:h";
@@ -179,97 +196,105 @@ void parseOptions(int argc, char* argv[]) {
opterr = 0;
while (true) {
-
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, SHORT_OPTIONS, LONG_OPTIONS, &option_index);
- if (c == -1)
- break;
+ if (c == -1) break;
switch (c) {
- case 0:
- // Option set a flag, don't need to do anything
- // (although none of the current LONG_OPTIONS do this...)
- break;
-
- case LongOpts::List:
- listTests();
- exit(EXIT_SUCCESS);
- break;
-
- case 'c':
- gOpts.count = atoi(optarg);
- if (!gOpts.count) {
- fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
- error = true;
- }
- break;
+ case 0:
+ // Option set a flag, don't need to do anything
+ // (although none of the current LONG_OPTIONS do this...)
+ break;
- case 'r':
- gRepeatCount = atoi(optarg);
- if (!gRepeatCount) {
- fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
- error = true;
- } else {
- gRepeatCount = (gRepeatCount > 0 ? gRepeatCount : INT_MAX);
- }
- break;
+ case LongOpts::List:
+ listTests();
+ exit(EXIT_SUCCESS);
+ break;
- case LongOpts::ReportFrametime:
- if (optarg) {
- gOpts.reportFrametimeWeight = atoi(optarg);
- if (!gOpts.reportFrametimeWeight) {
- fprintf(stderr, "Invalid report frametime weight '%s'\n", optarg);
+ case 'c':
+ gOpts.count = atoi(optarg);
+ if (!gOpts.count) {
+ fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
error = true;
}
- } else {
- gOpts.reportFrametimeWeight = 10;
- }
- break;
+ break;
- case LongOpts::WaitForGpu:
- Properties::waitForGpuCompletion = true;
- break;
+ case 'r':
+ gRepeatCount = atoi(optarg);
+ if (!gRepeatCount) {
+ fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
+ error = true;
+ } else {
+ gRepeatCount = (gRepeatCount > 0 ? gRepeatCount : INT_MAX);
+ }
+ break;
- case LongOpts::CpuSet:
- if (!optarg) {
- error = true;
+ case LongOpts::ReportFrametime:
+ if (optarg) {
+ gOpts.reportFrametimeWeight = atoi(optarg);
+ if (!gOpts.reportFrametimeWeight) {
+ fprintf(stderr, "Invalid report frametime weight '%s'\n", optarg);
+ error = true;
+ }
+ } else {
+ gOpts.reportFrametimeWeight = 10;
+ }
break;
- }
- moveToCpuSet(optarg);
- break;
- case LongOpts::BenchmarkFormat:
- if (!optarg) {
- error = true;
+ case LongOpts::WaitForGpu:
+ Properties::waitForGpuCompletion = true;
break;
- }
- if (!setBenchmarkFormat(optarg)) {
- error = true;
- }
- break;
- case LongOpts::Onscreen:
- gOpts.renderOffscreen = false;
- break;
+ case LongOpts::CpuSet:
+ if (!optarg) {
+ error = true;
+ break;
+ }
+ moveToCpuSet(optarg);
+ break;
- case LongOpts::Offscreen:
- gOpts.renderOffscreen = true;
- break;
+ case LongOpts::BenchmarkFormat:
+ if (!optarg) {
+ error = true;
+ break;
+ }
+ if (!setBenchmarkFormat(optarg)) {
+ error = true;
+ }
+ break;
- case 'h':
- printHelp();
- exit(EXIT_SUCCESS);
- break;
+ case LongOpts::Renderer:
+ if (!optarg) {
+ error = true;
+ break;
+ }
+ if (!setRenderer(optarg)) {
+ error = true;
+ }
+ break;
+
+ case LongOpts::Onscreen:
+ gOpts.renderOffscreen = false;
+ break;
- case '?':
- fprintf(stderr, "Unrecognized option '%s'\n", argv[optind - 1]);
+ case LongOpts::Offscreen:
+ gOpts.renderOffscreen = true;
+ break;
+
+ case 'h':
+ printHelp();
+ exit(EXIT_SUCCESS);
+ break;
+
+ case '?':
+ fprintf(stderr, "Unrecognized option '%s'\n", argv[optind - 1]);
// fall-through
- default:
- error = true;
- break;
+ default:
+ error = true;
+ break;
}
}
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index f166c5ceb974..0aaf7731c927 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -114,7 +114,7 @@ void BM_DisplayListCanvas_record_simpleBitmapView(benchmark::State& benchState)
}
BENCHMARK(BM_DisplayListCanvas_record_simpleBitmapView);
-class NullClient: public CanvasStateClient {
+class NullClient : public CanvasStateClient {
void onViewportInitialized() override {}
void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
GLuint getTargetFbo() const override { return 0; }
@@ -161,8 +161,7 @@ void BM_CanvasState_translate(benchmark::State& benchState) {
BENCHMARK(BM_CanvasState_translate);
void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) {
- sp<RenderNode> child = TestUtils::createNode(50, 50, 100, 100,
- [](auto& props, auto& canvas) {
+ sp<RenderNode> child = TestUtils::createNode(50, 50, 100, 100, [](auto& props, auto& canvas) {
canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
});
@@ -171,8 +170,7 @@ void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) {
while (benchState.KeepRunning()) {
canvas->resetRecording(200, 200);
- canvas->setHighContrastText(false);
- canvas->translate(0, 0); // mScrollX, mScrollY
+ canvas->translate(0, 0); // mScrollX, mScrollY
// Clip to padding
// Can expect ~25% of views to have clip to padding with a non-null padding
diff --git a/libs/hwui/tests/microbench/FontBench.cpp b/libs/hwui/tests/microbench/FontBench.cpp
index df3d041e722d..4e9b540a5c3d 100644
--- a/libs/hwui/tests/microbench/FontBench.cpp
+++ b/libs/hwui/tests/microbench/FontBench.cpp
@@ -37,8 +37,8 @@ void BM_FontRenderer_precache_cachehits(benchmark::State& state) {
std::vector<float> positions;
float totalAdvance;
uirenderer::Rect bounds;
- TestUtils::layoutTextUnscaled(paint, "This is a test",
- &glyphs, &positions, &totalAdvance, &bounds);
+ TestUtils::layoutTextUnscaled(paint, "This is a test", &glyphs, &positions, &totalAdvance,
+ &bounds);
fontRenderer.precache(&paint, glyphs.data(), glyphs.size(), SkMatrix::I());
diff --git a/libs/hwui/tests/microbench/FrameBuilderBench.cpp b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
index a5e85df22c8e..b6217665d743 100644
--- a/libs/hwui/tests/microbench/FrameBuilderBench.cpp
+++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
@@ -16,17 +16,17 @@
#include <benchmark/benchmark.h>
-#include "BakedOpState.h"
#include "BakedOpDispatcher.h"
#include "BakedOpRenderer.h"
+#include "BakedOpState.h"
#include "FrameBuilder.h"
#include "LayerUpdateQueue.h"
#include "RecordedOp.h"
#include "RecordingCanvas.h"
+#include "Vector.h"
#include "tests/common/TestContext.h"
#include "tests/common/TestScene.h"
#include "tests/common/TestUtils.h"
-#include "Vector.h"
#include <vector>
@@ -35,25 +35,25 @@ using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::test;
-const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
-const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
+const FrameBuilder::LightGeometry sLightGeometry = {{100, 100, 100}, 50};
+const BakedOpRenderer::LightInfo sLightInfo = {128, 128};
static sp<RenderNode> createTestNode() {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- sk_sp<Bitmap> bitmap(TestUtils::createBitmap(10, 10));
- SkPaint paint;
-
- // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
- // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
- canvas.save(SaveFlags::MatrixClip);
- for (int i = 0; i < 30; i++) {
- canvas.translate(0, 10);
- canvas.drawRect(0, 0, 10, 10, paint);
- canvas.drawBitmap(*bitmap, 5, 0, nullptr);
- }
- canvas.restore();
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(10, 10));
+ SkPaint paint;
+
+ // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
+ // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
+ canvas.save(SaveFlags::MatrixClip);
+ for (int i = 0; i < 30; i++) {
+ canvas.translate(0, 10);
+ canvas.drawRect(0, 0, 10, 10, paint);
+ canvas.drawBitmap(*bitmap, 5, 0, nullptr);
+ }
+ canvas.restore();
+ });
TestUtils::syncHierarchyPropertiesAndDisplayList(node);
return node;
}
@@ -62,8 +62,8 @@ void BM_FrameBuilder_defer(benchmark::State& state) {
TestUtils::runOnRenderThread([&state](RenderThread& thread) {
auto node = createTestNode();
while (state.KeepRunning()) {
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*node);
benchmark::DoNotOptimize(&frameBuilder);
}
@@ -79,8 +79,7 @@ void BM_FrameBuilder_deferAndRender(benchmark::State& state) {
Caches& caches = Caches::getInstance();
while (state.KeepRunning()) {
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200,
- sLightGeometry, caches);
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, sLightGeometry, caches);
frameBuilder.deferRenderNode(*node);
BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo);
@@ -92,16 +91,17 @@ void BM_FrameBuilder_deferAndRender(benchmark::State& state) {
BENCHMARK(BM_FrameBuilder_deferAndRender);
static sp<RenderNode> getSyncedSceneNode(const char* sceneName) {
- gDisplay = getBuiltInDisplay(); // switch to real display if present
+ gDisplay = getBuiltInDisplay(); // switch to real display if present
TestContext testContext;
TestScene::Options opts;
std::unique_ptr<TestScene> scene(TestScene::testMap()[sceneName].createScene(opts));
- sp<RenderNode> rootNode = TestUtils::createNode<RecordingCanvas>(0, 0, gDisplay.w, gDisplay.h,
- [&scene](RenderProperties& props, RecordingCanvas& canvas) {
- scene->createContent(gDisplay.w, gDisplay.h, canvas);
- });
+ sp<RenderNode> rootNode = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, gDisplay.w, gDisplay.h,
+ [&scene](RenderProperties& props, RecordingCanvas& canvas) {
+ scene->createContent(gDisplay.w, gDisplay.h, canvas);
+ });
TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
return rootNode;
@@ -117,9 +117,8 @@ void BM_FrameBuilder_defer_scene(benchmark::State& state) {
state.SetLabel(sceneName);
auto node = getSyncedSceneNode(sceneName);
while (state.KeepRunning()) {
- FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h),
- gDisplay.w, gDisplay.h,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w,
+ gDisplay.h, sLightGeometry, Caches::getInstance());
frameBuilder.deferRenderNode(*node);
benchmark::DoNotOptimize(&frameBuilder);
}
@@ -137,9 +136,8 @@ void BM_FrameBuilder_deferAndRender_scene(benchmark::State& state) {
Caches& caches = Caches::getInstance();
while (state.KeepRunning()) {
- FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h),
- gDisplay.w, gDisplay.h,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w,
+ gDisplay.h, sLightGeometry, Caches::getInstance());
frameBuilder.deferRenderNode(*node);
BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo);
diff --git a/libs/hwui/tests/microbench/PathParserBench.cpp b/libs/hwui/tests/microbench/PathParserBench.cpp
index b43c4c3b63c1..00ae8c11124f 100644
--- a/libs/hwui/tests/microbench/PathParserBench.cpp
+++ b/libs/hwui/tests/microbench/PathParserBench.cpp
@@ -24,7 +24,9 @@
using namespace android;
using namespace android::uirenderer;
-static const char* sPathString = "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10";
+static const char* sPathString =
+ "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 "
+ "8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10";
void BM_PathParser_parseStringPathForSkPath(benchmark::State& state) {
SkPath skPath;
diff --git a/libs/hwui/tests/microbench/RenderNodeBench.cpp b/libs/hwui/tests/microbench/RenderNodeBench.cpp
index a5bed0026b1c..206dcd58d785 100644
--- a/libs/hwui/tests/microbench/RenderNodeBench.cpp
+++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp
@@ -30,4 +30,3 @@ void BM_RenderNode_create(benchmark::State& state) {
}
}
BENCHMARK(BM_RenderNode_create);
-
diff --git a/libs/hwui/tests/microbench/ShadowBench.cpp b/libs/hwui/tests/microbench/ShadowBench.cpp
index a0fc6e8f9f53..12da7837e2e9 100644
--- a/libs/hwui/tests/microbench/ShadowBench.cpp
+++ b/libs/hwui/tests/microbench/ShadowBench.cpp
@@ -18,9 +18,9 @@
#include "Matrix.h"
#include "Rect.h"
+#include "TessellationCache.h"
#include "Vector.h"
#include "VertexBuffer.h"
-#include "TessellationCache.h"
#include <SkPath.h>
@@ -40,22 +40,13 @@ struct ShadowTestData {
void createShadowTestData(ShadowTestData* out) {
static float SAMPLE_DRAW_TRANSFORM[] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
};
static float SAMPLE_CASTERXY[] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 32, 32, 0, 1,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 32, 32, 0, 1,
};
static float SAMPLE_CASTERZ[] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 32, 32, 32, 1,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 32, 32, 32, 1,
};
static Rect SAMPLE_CLIP(0, 0, 1536, 2048);
static Vector3 SAMPLE_LIGHT_CENTER{768, -400, 1600};
@@ -69,12 +60,11 @@ void createShadowTestData(ShadowTestData* out) {
out->lightRadius = SAMPLE_LIGHT_RADIUS;
}
-static inline void tessellateShadows(ShadowTestData& testData, bool opaque,
- const SkPath& shape, VertexBuffer* ambient, VertexBuffer* spot) {
- tessellateShadows(&testData.drawTransform, &testData.localClip,
- opaque, &shape, &testData.casterTransformXY,
- &testData.casterTransformZ, testData.lightCenter,
- testData.lightRadius, *ambient, *spot);
+static inline void tessellateShadows(ShadowTestData& testData, bool opaque, const SkPath& shape,
+ VertexBuffer* ambient, VertexBuffer* spot) {
+ tessellateShadows(&testData.drawTransform, &testData.localClip, opaque, &shape,
+ &testData.casterTransformXY, &testData.casterTransformZ, testData.lightCenter,
+ testData.lightRadius, *ambient, *spot);
}
void BM_TessellateShadows_roundrect_opaque(benchmark::State& state) {
diff --git a/libs/hwui/tests/microbench/TaskManagerBench.cpp b/libs/hwui/tests/microbench/TaskManagerBench.cpp
index cf47f273c144..4153baec22b5 100644
--- a/libs/hwui/tests/microbench/TaskManagerBench.cpp
+++ b/libs/hwui/tests/microbench/TaskManagerBench.cpp
@@ -19,7 +19,9 @@
#include "thread/Task.h"
#include "thread/TaskManager.h"
#include "thread/TaskProcessor.h"
+#include "thread/ThreadBase.h"
+#include <atomic>
#include <vector>
using namespace android;
@@ -29,17 +31,18 @@ class TrivialTask : public Task<char> {};
class TrivialProcessor : public TaskProcessor<char> {
public:
- explicit TrivialProcessor(TaskManager* manager)
- : TaskProcessor(manager) {}
+ explicit TrivialProcessor(TaskManager* manager) : TaskProcessor(manager) {}
virtual ~TrivialProcessor() {}
- virtual void onProcess(const sp<Task<char> >& task) override {
+ virtual void onProcess(const sp<Task<char>>& task) override {
TrivialTask* t = static_cast<TrivialTask*>(task.get());
t->setResult(reinterpret_cast<intptr_t>(t) % 16 == 0 ? 'a' : 'b');
}
};
+class TestThread : public ThreadBase, public virtual RefBase {};
+
void BM_TaskManager_allocateTask(benchmark::State& state) {
- std::vector<sp<TrivialTask> > tasks;
+ std::vector<sp<TrivialTask>> tasks;
tasks.reserve(state.max_iterations);
while (state.KeepRunning()) {
@@ -52,7 +55,7 @@ BENCHMARK(BM_TaskManager_allocateTask);
void BM_TaskManager_enqueueTask(benchmark::State& state) {
TaskManager taskManager;
sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
- std::vector<sp<TrivialTask> > tasks;
+ std::vector<sp<TrivialTask>> tasks;
tasks.reserve(state.max_iterations);
while (state.KeepRunning()) {
@@ -70,7 +73,7 @@ BENCHMARK(BM_TaskManager_enqueueTask);
void BM_TaskManager_enqueueRunDeleteTask(benchmark::State& state) {
TaskManager taskManager;
sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
- std::vector<sp<TrivialTask> > tasks;
+ std::vector<sp<TrivialTask>> tasks;
tasks.reserve(state.max_iterations);
while (state.KeepRunning()) {
@@ -86,3 +89,46 @@ void BM_TaskManager_enqueueRunDeleteTask(benchmark::State& state) {
state.PauseTiming();
}
BENCHMARK(BM_TaskManager_enqueueRunDeleteTask);
+
+void BM_Thread_enqueueTask(benchmark::State& state) {
+ sp<TestThread> thread{new TestThread};
+ thread->start();
+
+ atomic_int counter(0);
+ int expected = 0;
+ while (state.KeepRunning()) {
+ expected++;
+ thread->queue().post([&counter]() { counter++; });
+ }
+ thread->queue().runSync([]() {});
+
+ thread->requestExit();
+ thread->join();
+ if (counter != expected) {
+ printf("Ran %d lambads, should have been %d\n", counter.load(), expected);
+ }
+}
+BENCHMARK(BM_Thread_enqueueTask);
+
+void BM_Thread_enqueueRunDeleteTask(benchmark::State& state) {
+ sp<TestThread> thread{new TestThread};
+ thread->start();
+ std::vector<std::future<int>> tasks;
+ tasks.reserve(state.max_iterations);
+
+ int expected = 0;
+ while (state.KeepRunning()) {
+ tasks.emplace_back(thread->queue().async([expected]() -> int { return expected + 1; }));
+ expected++;
+ }
+ state.ResumeTiming();
+ expected = 0;
+ for (auto& future : tasks) {
+ if (future.get() != ++expected) {
+ printf("Mismatch expected %d vs. observed %d\n", expected, future.get());
+ }
+ }
+ tasks.clear();
+ state.PauseTiming();
+}
+BENCHMARK(BM_Thread_enqueueRunDeleteTask); \ No newline at end of file
diff --git a/libs/hwui/tests/scripts/prep_taieye.sh b/libs/hwui/tests/scripts/prep_taieye.sh
new file mode 100755
index 000000000000..503f6d5d5239
--- /dev/null
+++ b/libs/hwui/tests/scripts/prep_taieye.sh
@@ -0,0 +1,50 @@
+nr=$(adb shell cat /proc/cpuinfo | grep processor | wc -l)
+cpubase=/sys/devices/system/cpu
+
+adb root
+adb wait-for-device
+adb shell stop vendor.perfd
+adb shell stop thermal-engine
+
+S=1036800
+cpu=0
+# Changing governor and frequency in one core will be automatically applied
+# to other cores in the cluster
+while [ $((cpu < 4)) -eq 1 ]; do
+ echo "Setting cpu ${cpu} to $S hz"
+ adb shell "echo userspace > $cpubase/cpu${cpu}/cpufreq/scaling_governor"
+ adb shell "echo 1 > $cpubase/cpu${cpu}/online"
+ adb shell "echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_max_freq"
+ adb shell "echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_min_freq"
+ cpu=$(($cpu + 1))
+done
+
+while [ $((cpu < $nr)) -eq 1 ]; do
+ echo "disable cpu $cpu"
+ adb shell "echo 0 > $cpubase/cpu${cpu}/online"
+ cpu=$(($cpu + 1))
+done
+
+echo "setting GPU bus and idle timer"
+adb shell "echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split"
+adb shell "echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on"
+adb shell "echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer"
+
+#0 762 1144 1525 2288 3143 4173 5195 5859 7759 9887 11863 13763
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,gpubw/min_freq"
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,gpubw/max_freq"
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,cpubw/min_freq"
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,cpubw/max_freq"
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,mincpubw/min_freq"
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,mincpubw/max_freq"
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,memlat-cpu0/min_freq"
+adb shell "echo 7759 > /sys/class/devfreq/soc\:qcom,memlat-cpu0/max_freq"
+
+# 180000000 257000000 342000000 414000000 515000000 596000000 670000000 710000000
+echo "performance mode, 342 MHz"
+adb shell "echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor"
+adb shell "echo 342000000 > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq"
+adb shell "echo 342000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq"
+
+adb shell "echo 4 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel"
+adb shell "echo 4 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel"
diff --git a/libs/hwui/tests/scripts/skp-capture.sh b/libs/hwui/tests/scripts/skp-capture.sh
new file mode 100755
index 000000000000..54fa22929586
--- /dev/null
+++ b/libs/hwui/tests/scripts/skp-capture.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+# Copyright 2015 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if [ -z "$1" ]; then
+ printf 'Usage:\n skp-capture.sh PACKAGE_NAME OPTIONAL_FRAME_COUNT\n\n'
+ printf "Use \`adb shell 'pm list packages'\` to get a listing.\n\n"
+ exit 1
+fi
+if ! command -v adb > /dev/null 2>&1; then
+ if [ -x "${ANDROID_SDK_ROOT}/platform-tools/adb" ]; then
+ adb() {
+ "${ANDROID_SDK_ROOT}/platform-tools/adb" "$@"
+ }
+ else
+ echo 'adb missing'
+ exit 2
+ fi
+fi
+phase1_timeout_seconds=15
+phase2_timeout_seconds=60
+package="$1"
+filename="$(date '+%H%M%S').skp"
+remote_path="/data/data/${package}/cache/${filename}"
+local_path_prefix="$(date '+%Y-%m-%d_%H%M%S')_${package}"
+local_path="${local_path_prefix}.skp"
+enable_capture_key='debug.hwui.capture_skp_enabled'
+enable_capture_value=$(adb shell "getprop '${enable_capture_key}'")
+#printf 'captureflag=' "$enable_capture_value" '\n'
+if [ -z "$enable_capture_value" ]; then
+ printf 'Capture SKP property need to be enabled first. Please use\n'
+ printf "\"adb shell setprop debug.hwui.capture_skp_enabled true\" and then restart\n"
+ printf "the process.\n\n"
+ exit 1
+fi
+if [ ! -z "$2" ]; then
+ adb shell "setprop 'debug.hwui.capture_skp_frames' $2"
+fi
+filename_key='debug.hwui.skp_filename'
+adb shell "setprop '${filename_key}' '${remote_path}'"
+spin() {
+ case "$spin" in
+ 1) printf '\b|';;
+ 2) printf '\b\\';;
+ 3) printf '\b-';;
+ *) printf '\b/';;
+ esac
+ spin=$(( ( ${spin:-0} + 1 ) % 4 ))
+ sleep $1
+}
+
+banner() {
+ printf '\n=====================\n'
+ printf ' %s' "$*"
+ printf '\n=====================\n'
+}
+banner '...WAITING...'
+adb_test_exist() {
+ test '0' = "$(adb shell "test -e \"$1\"; echo \$?")";
+}
+timeout=$(( $(date +%s) + $phase1_timeout_seconds))
+while ! adb_test_exist "$remote_path"; do
+ spin 0.05
+ if [ $(date +%s) -gt $timeout ] ; then
+ printf '\bTimed out.\n'
+ adb shell "setprop '${filename_key}' ''"
+ exit 3
+ fi
+done
+printf '\b'
+
+#read -n1 -r -p "Press any key to continue..." key
+
+banner '...SAVING...'
+adb_test_file_nonzero() {
+ # grab first byte of `du` output
+ X="$(adb shell "du \"$1\" 2> /dev/null | dd bs=1 count=1 2> /dev/null")"
+ test "$X" && test "$X" -ne 0
+}
+#adb_filesize() {
+# adb shell "wc -c \"$1\"" 2> /dev/null | awk '{print $1}'
+#}
+timeout=$(( $(date +%s) + $phase2_timeout_seconds))
+while ! adb_test_file_nonzero "$remote_path"; do
+ spin 0.05
+ if [ $(date +%s) -gt $timeout ] ; then
+ printf '\bTimed out.\n'
+ adb shell "setprop '${filename_key}' ''"
+ exit 3
+ fi
+done
+printf '\b'
+
+adb shell "setprop '${filename_key}' ''"
+
+i=0; while [ $i -lt 10 ]; do spin 0.10; i=$(($i + 1)); done; echo
+
+adb pull "$remote_path" "$local_path"
+if ! [ -f "$local_path" ] ; then
+ printf "something went wrong with `adb pull`."
+ exit 4
+fi
+adb shell rm "$remote_path"
+printf '\nSKP saved to file:\n %s\n\n' "$local_path"
+if [ ! -z "$2" ]; then
+ bridge="_"
+ adb shell "setprop 'debug.hwui.capture_skp_frames' ''"
+ for i in $(seq 2 $2); do
+ adb pull "${remote_path}_${i}" "${local_path_prefix}_${i}.skp"
+ adb shell rm "${remote_path}_${i}"
+ done
+fi
+
diff --git a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
index b0ef11f26bdd..09f0b06ded39 100644
--- a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
@@ -20,8 +20,8 @@
#include <BakedOpRenderer.h>
#include <FrameBuilder.h>
#include <LayerUpdateQueue.h>
-#include <hwui/Paint.h>
#include <RecordedOp.h>
+#include <hwui/Paint.h>
#include <tests/common/TestUtils.h>
#include <utils/Color.h>
@@ -32,19 +32,20 @@
using namespace android::uirenderer;
static BakedOpRenderer::LightInfo sLightInfo;
-const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
+const FrameBuilder::LightGeometry sLightGeometry = {{100, 100, 100}, 50};
class ValidatingBakedOpRenderer : public BakedOpRenderer {
public:
- ValidatingBakedOpRenderer(RenderState& renderState, std::function<void(const Glop& glop)> validator)
+ ValidatingBakedOpRenderer(RenderState& renderState,
+ std::function<void(const Glop& glop)> validator)
: BakedOpRenderer(Caches::getInstance(), renderState, true, false, sLightInfo)
, mValidator(validator) {
mGlopReceiver = ValidatingGlopReceiver;
}
+
private:
static void ValidatingGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds,
- const ClipBase* clip, const Glop& glop) {
-
+ const ClipBase* clip, const Glop& glop) {
auto vbor = reinterpret_cast<ValidatingBakedOpRenderer*>(&renderer);
vbor->mValidator(glop);
}
@@ -54,7 +55,8 @@ private:
typedef void (*TestBakedOpReceiver)(BakedOpRenderer&, const BakedOpState&);
static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op,
- std::function<void(const Glop& glop)> glopVerifier, int expectedGlopCount = 1) {
+ std::function<void(const Glop& glop)> glopVerifier,
+ int expectedGlopCount = 1) {
// Create op, and wrap with basic state.
LinearAllocator allocator;
auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 100));
@@ -62,22 +64,22 @@ static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, R
ASSERT_NE(nullptr, state);
int glopCount = 0;
- auto glopReceiver = [&glopVerifier, &glopCount, &expectedGlopCount] (const Glop& glop) {
+ auto glopReceiver = [&glopVerifier, &glopCount, &expectedGlopCount](const Glop& glop) {
ASSERT_LE(glopCount++, expectedGlopCount) << expectedGlopCount << "glop(s) expected";
glopVerifier(glop);
};
ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver);
- // Dispatch based on op type created, similar to Frame/LayerBuilder dispatch behavior
-#define X(Type) \
- [](BakedOpRenderer& renderer, const BakedOpState& state) { \
- BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \
- },
+// Dispatch based on op type created, similar to Frame/LayerBuilder dispatch behavior
+#define X(Type) \
+ [](BakedOpRenderer& renderer, const BakedOpState& state) { \
+ BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \
+ },
static TestBakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X);
#undef X
unmergedReceivers[op->opId](renderer, *state);
ASSERT_EQ(expectedGlopCount, glopCount) << "Exactly " << expectedGlopCount
- << "Glop(s) expected";
+ << "Glop(s) expected";
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTexture_positionOvalArc) {
@@ -88,7 +90,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTexture_positionOvalArc
float intervals[] = {1.0f, 1.0f};
strokePaint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
- auto textureGlopVerifier = [] (const Glop& glop) {
+ auto textureGlopVerifier = [](const Glop& glop) {
// validate glop produced by renderPathTexture (so texture, unit quad)
auto texture = glop.fill.texture.texture;
ASSERT_NE(nullptr, texture);
@@ -116,16 +118,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTexture_positionOvalArc
RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, onLayerOp_bufferless) {
SkPaint layerPaint;
layerPaint.setAlpha(128);
- OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case
+ OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case
LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer);
- testUnmergedGlopDispatch(renderThread, &op, [] (const Glop& glop) {
- ADD_FAILURE() << "Nothing should happen";
- }, 0);
+ testUnmergedGlopDispatch(renderThread, &op,
+ [](const Glop& glop) { ADD_FAILURE() << "Nothing should happen"; }, 0);
}
static int getGlopTransformFlags(renderthread::RenderThread& renderThread, RecordedOp* op) {
int result = 0;
- testUnmergedGlopDispatch(renderThread, op, [&result] (const Glop& glop) {
+ testUnmergedGlopDispatch(renderThread, op, [&result](const Glop& glop) {
result = glop.transform.transformFlags;
});
return result;
@@ -144,7 +145,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, offsetFlags) {
const float points[4] = {0.5, 0.5, 1.0, 1.0};
PointsOp antiAliasedPointsOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4);
EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedPointsOp))
- << "Expect no offset for AA points.";
+ << "Expect no offset for AA points.";
PointsOp pointsOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4);
EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &pointsOp))
<< "Expect an offset for non-AA points.";
@@ -158,21 +159,21 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, offsetFlags) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, renderTextWithShadow) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
- android::Paint shadowPaint;
- shadowPaint.setColor(SK_ColorRED);
+ android::Paint shadowPaint;
+ shadowPaint.setColor(SK_ColorRED);
- SkScalar sigma = Blur::convertRadiusToSigma(5);
- shadowPaint.setLooper(SkBlurDrawLooper::Make(SK_ColorWHITE, sigma, 3, 3));
+ SkScalar sigma = Blur::convertRadiusToSigma(5);
+ shadowPaint.setLooper(SkBlurDrawLooper::Make(SK_ColorWHITE, sigma, 3, 3));
- TestUtils::drawUtf8ToCanvas(&canvas, "A", shadowPaint, 25, 25);
- TestUtils::drawUtf8ToCanvas(&canvas, "B", shadowPaint, 50, 50);
- });
+ TestUtils::drawUtf8ToCanvas(&canvas, "A", shadowPaint, 25, 25);
+ TestUtils::drawUtf8ToCanvas(&canvas, "B", shadowPaint, 50, 50);
+ });
- int glopCount = 0;
- auto glopReceiver = [&glopCount] (const Glop& glop) {
+ int glopCount = 0;
+ auto glopReceiver = [&glopCount](const Glop& glop) {
if (glopCount < 2) {
// two white shadows
EXPECT_EQ(FloatColor({1, 1, 1, 1}), glop.fill.color);
@@ -185,8 +186,8 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, renderTextWithShadow) {
ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver);
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
@@ -194,15 +195,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, renderTextWithShadow) {
}
static void validateLayerDraw(renderthread::RenderThread& renderThread,
- std::function<void(const Glop& glop)> validator) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- props.mutateLayerProperties().setType(LayerType::RenderLayer);
-
- // provide different blend mode, so decoration draws contrast
- props.mutateLayerProperties().setXferMode(SkBlendMode::kSrc);
- canvas.drawColor(Color::Black, SkBlendMode::kSrcOver);
- });
+ std::function<void(const Glop& glop)> validator) {
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
+
+ // provide different blend mode, so decoration draws contrast
+ props.mutateLayerProperties().setXferMode(SkBlendMode::kSrc);
+ canvas.drawColor(Color::Black, SkBlendMode::kSrcOver);
+ });
OffscreenBuffer** layerHandle = node->getLayerHandle();
auto syncedNode = TestUtils::getSyncedNode(node);
@@ -211,12 +212,12 @@ static void validateLayerDraw(renderthread::RenderThread& renderThread,
OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
*layerHandle = &layer;
{
- LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(0, 0, 100, 100));
ValidatingBakedOpRenderer renderer(renderThread.renderState(), validator);
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferLayers(layerUpdateQueue);
frameBuilder.deferRenderNode(*syncedNode);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
@@ -233,8 +234,8 @@ static FloatColor makeFloatColor(uint32_t color) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, layerUpdateProperties) {
- for (bool debugOverdraw : { false, true }) {
- for (bool debugLayersUpdates : { false, true }) {
+ for (bool debugOverdraw : {false, true}) {
+ for (bool debugLayersUpdates : {false, true}) {
ScopedProperty<bool> ovdProp(Properties::debugOverdraw, debugOverdraw);
ScopedProperty<bool> lupProp(Properties::debugLayersUpdates, debugLayersUpdates);
@@ -253,8 +254,8 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, layerUpdateProperties) {
// blend srcover, different from that of layer
EXPECT_EQ(GLenum(GL_ONE), glop.blend.src);
EXPECT_EQ(GLenum(GL_ONE_MINUS_SRC_ALPHA), glop.blend.dst);
- EXPECT_EQ(makeFloatColor(debugLayersUpdates ? 0x7f00ff00 : 0),
- glop.fill.color) << "Should be transparent green if debugLayersUpdates";
+ EXPECT_EQ(makeFloatColor(debugLayersUpdates ? 0x7f00ff00 : 0), glop.fill.color)
+ << "Should be transparent green if debugLayersUpdates";
} else if (glopCount < 7) {
// 3 - 6 - overdraw indicator overlays, if present
EXPECT_TRUE(glop.fill.colorEnabled);
@@ -279,7 +280,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTextureSnapping) {
SkPath path;
path.addRect(SkRect::MakeXYWH(1.5, 3.8, 100, 90));
PathOp op(bounds, Matrix4::identity(), nullptr, &paint, &path);
- testUnmergedGlopDispatch(renderThread, &op, [] (const Glop& glop) {
+ testUnmergedGlopDispatch(renderThread, &op, [](const Glop& glop) {
auto texture = glop.fill.texture.texture;
ASSERT_NE(nullptr, texture);
EXPECT_EQ(1, reinterpret_cast<PathTexture*>(texture)->left);
diff --git a/libs/hwui/tests/unit/BakedOpRendererTests.cpp b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
index 38e106a8ab77..1a3ec39a00d0 100644
--- a/libs/hwui/tests/unit/BakedOpRendererTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
@@ -22,11 +22,11 @@
using namespace android::uirenderer;
-const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
+const BakedOpRenderer::LightInfo sLightInfo = {128, 128};
RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpRenderer, startRepaintLayer_clear) {
- BakedOpRenderer renderer(Caches::getInstance(), renderThread.renderState(),
- true, false, sLightInfo);
+ BakedOpRenderer renderer(Caches::getInstance(), renderThread.renderState(), true, false,
+ sLightInfo);
OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200u, 200u);
layer.dirty(Rect(200, 200));
@@ -38,9 +38,9 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpRenderer, startRepaintLayer_clear) {
layer.dirty(Rect(200, 200));
{
- renderer.startRepaintLayer(&layer, Rect(100, 200)); // repainting left side
+ renderer.startRepaintLayer(&layer, Rect(100, 200)); // repainting left side
EXPECT_TRUE(layer.region.isRect());
- //ALOGD("bounds %d %d %d %d", RECT_ARGS(layer.region.getBounds()));
+ // ALOGD("bounds %d %d %d %d", RECT_ARGS(layer.region.getBounds()));
EXPECT_EQ(android::Rect(100, 0, 200, 200), layer.region.getBounds())
<< "Left side being repainted, so right side should be clear";
renderer.endLayer();
@@ -48,7 +48,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpRenderer, startRepaintLayer_clear) {
// right side is now only dirty portion
{
- renderer.startRepaintLayer(&layer, Rect(100, 0, 200, 200)); // repainting right side
+ renderer.startRepaintLayer(&layer, Rect(100, 0, 200, 200)); // repainting right side
EXPECT_TRUE(layer.region.isEmpty())
<< "Now right side being repainted, so region should be entirely clear";
renderer.endLayer();
diff --git a/libs/hwui/tests/unit/BakedOpStateTests.cpp b/libs/hwui/tests/unit/BakedOpStateTests.cpp
index d51db2ebb169..6f8e24917767 100644
--- a/libs/hwui/tests/unit/BakedOpStateTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpStateTests.cpp
@@ -38,7 +38,7 @@ TEST(ResolvedRenderState, construct) {
ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false, false);
EXPECT_MATRIX_APPROX_EQ(state.transform, translate10x20);
EXPECT_EQ(Rect(100, 200), state.clipRect());
- EXPECT_EQ(Rect(40, 60, 100, 200), state.clippedBounds); // translated and also clipped
+ EXPECT_EQ(Rect(40, 60, 100, 200), state.clippedBounds); // translated and also clipped
EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom, state.clipSideFlags);
}
{
@@ -72,14 +72,14 @@ TEST(ResolvedRenderState, computeLocalSpaceClip) {
auto parentSnapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 200));
ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false, false);
EXPECT_EQ(Rect(-10, -20, 90, 180), state.computeLocalSpaceClip())
- << "Local clip rect should be 100x200, offset by -10,-20";
+ << "Local clip rect should be 100x200, offset by -10,-20";
}
{
// recorded with transform + parent transform
auto parentSnapshot = TestUtils::makeSnapshot(translate10x20, Rect(100, 200));
ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false, false);
EXPECT_EQ(Rect(-10, -20, 80, 160), state.computeLocalSpaceClip())
- << "Local clip rect should be 90x190, offset by -10,-20";
+ << "Local clip rect should be 90x190, offset by -10,-20";
}
}
@@ -96,62 +96,51 @@ struct StrokeTestCase {
};
const static StrokeTestCase sStrokeTestCases[] = {
- {
- 1, HAIRLINE, [](const ResolvedRenderState& state) {
- EXPECT_EQ(Rect(49.5f, 49.5f, 150.5f, 150.5f), state.clippedBounds);
- }
- },
- {
- 1, SEMI_HAIRLINE, [](const ResolvedRenderState& state) {
- EXPECT_TRUE(state.clippedBounds.contains(49.5f, 49.5f, 150.5f, 150.5f));
- EXPECT_TRUE(Rect(49, 49, 151, 151).contains(state.clippedBounds));
- }
- },
- {
- 1, 20, [](const ResolvedRenderState& state) {
- EXPECT_EQ(Rect(40, 40, 160, 160), state.clippedBounds);
- }
- },
-
- // 3x3 scale:
- {
- 3, HAIRLINE, [](const ResolvedRenderState& state) {
- EXPECT_EQ(Rect(149.5f, 149.5f, 200, 200), state.clippedBounds);
- EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom, state.clipSideFlags);
- }
- },
- {
- 3, SEMI_HAIRLINE, [](const ResolvedRenderState& state) {
- EXPECT_TRUE(state.clippedBounds.contains(149.5f, 149.5f, 200, 200));
- EXPECT_TRUE(Rect(149, 149, 200, 200).contains(state.clippedBounds));
- }
- },
- {
- 3, 20, [](const ResolvedRenderState& state) {
- EXPECT_TRUE(state.clippedBounds.contains(120, 120, 200, 200));
- EXPECT_TRUE(Rect(119, 119, 200, 200).contains(state.clippedBounds));
- }
- },
-
- // 0.5f x 0.5f scale
- {
- 0.5f, HAIRLINE, [](const ResolvedRenderState& state) {
- EXPECT_EQ(Rect(24.5f, 24.5f, 75.5f, 75.5f), state.clippedBounds);
- }
- },
- {
- 0.5f, SEMI_HAIRLINE, [](const ResolvedRenderState& state) {
- EXPECT_TRUE(state.clippedBounds.contains(24.5f, 24.5f, 75.5f, 75.5f));
- EXPECT_TRUE(Rect(24, 24, 76, 76).contains(state.clippedBounds));
- }
- },
- {
- 0.5f, 20, [](const ResolvedRenderState& state) {
- EXPECT_TRUE(state.clippedBounds.contains(19.5f, 19.5f, 80.5f, 80.5f));
- EXPECT_TRUE(Rect(19, 19, 81, 81).contains(state.clippedBounds));
- }
- }
-};
+ {1, HAIRLINE,
+ [](const ResolvedRenderState& state) {
+ EXPECT_EQ(Rect(49.5f, 49.5f, 150.5f, 150.5f), state.clippedBounds);
+ }},
+ {1, SEMI_HAIRLINE,
+ [](const ResolvedRenderState& state) {
+ EXPECT_TRUE(state.clippedBounds.contains(49.5f, 49.5f, 150.5f, 150.5f));
+ EXPECT_TRUE(Rect(49, 49, 151, 151).contains(state.clippedBounds));
+ }},
+ {1, 20,
+ [](const ResolvedRenderState& state) {
+ EXPECT_EQ(Rect(40, 40, 160, 160), state.clippedBounds);
+ }},
+
+ // 3x3 scale:
+ {3, HAIRLINE,
+ [](const ResolvedRenderState& state) {
+ EXPECT_EQ(Rect(149.5f, 149.5f, 200, 200), state.clippedBounds);
+ EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom, state.clipSideFlags);
+ }},
+ {3, SEMI_HAIRLINE,
+ [](const ResolvedRenderState& state) {
+ EXPECT_TRUE(state.clippedBounds.contains(149.5f, 149.5f, 200, 200));
+ EXPECT_TRUE(Rect(149, 149, 200, 200).contains(state.clippedBounds));
+ }},
+ {3, 20,
+ [](const ResolvedRenderState& state) {
+ EXPECT_TRUE(state.clippedBounds.contains(120, 120, 200, 200));
+ EXPECT_TRUE(Rect(119, 119, 200, 200).contains(state.clippedBounds));
+ }},
+
+ // 0.5f x 0.5f scale
+ {0.5f, HAIRLINE,
+ [](const ResolvedRenderState& state) {
+ EXPECT_EQ(Rect(24.5f, 24.5f, 75.5f, 75.5f), state.clippedBounds);
+ }},
+ {0.5f, SEMI_HAIRLINE,
+ [](const ResolvedRenderState& state) {
+ EXPECT_TRUE(state.clippedBounds.contains(24.5f, 24.5f, 75.5f, 75.5f));
+ EXPECT_TRUE(Rect(24, 24, 76, 76).contains(state.clippedBounds));
+ }},
+ {0.5f, 20, [](const ResolvedRenderState& state) {
+ EXPECT_TRUE(state.clippedBounds.contains(19.5f, 19.5f, 80.5f, 80.5f));
+ EXPECT_TRUE(Rect(19, 19, 81, 81).contains(state.clippedBounds));
+ }}};
TEST(ResolvedRenderState, construct_expandForStroke) {
LinearAllocator allocator;
@@ -163,8 +152,7 @@ TEST(ResolvedRenderState, construct_expandForStroke) {
strokedPaint.setStrokeWidth(testCase.strokeWidth);
ClipRect clip(Rect(200, 200));
- RectOp recordedOp(Rect(50, 50, 150, 150),
- Matrix4::identity(), &clip, &strokedPaint);
+ RectOp recordedOp(Rect(50, 50, 150, 150), Matrix4::identity(), &clip, &strokedPaint);
Matrix4 snapshotMatrix;
snapshotMatrix.loadScale(testCase.scale, testCase.scale, 1);
@@ -204,16 +192,18 @@ TEST(BakedOpState, tryShadowOpConstruct) {
LinearAllocator allocator;
{
- auto snapshot = TestUtils::makeSnapshot(translate10x20, Rect()); // Note: empty clip
- BakedOpState* bakedState = BakedOpState::tryShadowOpConstruct(allocator, *snapshot, (ShadowOp*)0x1234);
+ auto snapshot = TestUtils::makeSnapshot(translate10x20, Rect()); // Note: empty clip
+ BakedOpState* bakedState =
+ BakedOpState::tryShadowOpConstruct(allocator, *snapshot, (ShadowOp*)0x1234);
EXPECT_EQ(nullptr, bakedState) << "op should be rejected by clip, so not constructed";
EXPECT_EQ(0u, allocator.usedSize()) << "no serialization, even for clip,"
- "since op is quick rejected based on snapshot clip";
+ "since op is quick rejected based on snapshot clip";
}
{
auto snapshot = TestUtils::makeSnapshot(translate10x20, Rect(100, 200));
- BakedOpState* bakedState = BakedOpState::tryShadowOpConstruct(allocator, *snapshot, (ShadowOp*)0x1234);
+ BakedOpState* bakedState =
+ BakedOpState::tryShadowOpConstruct(allocator, *snapshot, (ShadowOp*)0x1234);
ASSERT_NE(nullptr, bakedState) << "NOT rejected by clip, so op should be constructed";
EXPECT_LE(64u, allocator.usedSize()) << "relatively large alloc for non-rejected op";
@@ -232,12 +222,13 @@ TEST(BakedOpState, tryStrokeableOpConstruct) {
paint.setStrokeWidth(0.0f);
ClipRect clip(Rect(100, 200));
RectOp rejectOp(Rect(100, 200), Matrix4::identity(), &clip, &paint);
- auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect()); // Note: empty clip
- auto bakedState = BakedOpState::tryStrokeableOpConstruct(allocator, *snapshot, rejectOp,
- BakedOpState::StrokeBehavior::StyleDefined, false);
+ auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect()); // Note: empty clip
+ auto bakedState = BakedOpState::tryStrokeableOpConstruct(
+ allocator, *snapshot, rejectOp, BakedOpState::StrokeBehavior::StyleDefined, false);
EXPECT_EQ(nullptr, bakedState);
- EXPECT_GT(8u, allocator.usedSize()); // no significant allocation space used for rejected op
+ EXPECT_GT(8u,
+ allocator.usedSize()); // no significant allocation space used for rejected op
}
{
// check simple unscaled expansion
@@ -247,8 +238,8 @@ TEST(BakedOpState, tryStrokeableOpConstruct) {
ClipRect clip(Rect(200, 200));
RectOp rejectOp(Rect(50, 50, 150, 150), Matrix4::identity(), &clip, &paint);
auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(200, 200));
- auto bakedState = BakedOpState::tryStrokeableOpConstruct(allocator, *snapshot, rejectOp,
- BakedOpState::StrokeBehavior::StyleDefined, false);
+ auto bakedState = BakedOpState::tryStrokeableOpConstruct(
+ allocator, *snapshot, rejectOp, BakedOpState::StrokeBehavior::StyleDefined, false);
ASSERT_NE(nullptr, bakedState);
EXPECT_EQ(Rect(45, 45, 155, 155), bakedState->computedState.clippedBounds);
@@ -262,8 +253,8 @@ TEST(BakedOpState, tryStrokeableOpConstruct) {
ClipRect clip(Rect(200, 200));
RectOp rejectOp(Rect(50, 50, 150, 150), Matrix4::identity(), &clip, &paint);
auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(200, 200));
- auto bakedState = BakedOpState::tryStrokeableOpConstruct(allocator, *snapshot, rejectOp,
- BakedOpState::StrokeBehavior::Forced, false);
+ auto bakedState = BakedOpState::tryStrokeableOpConstruct(
+ allocator, *snapshot, rejectOp, BakedOpState::StrokeBehavior::Forced, false);
ASSERT_NE(nullptr, bakedState);
EXPECT_EQ(Rect(45, 45, 155, 155), bakedState->computedState.clippedBounds);
@@ -271,5 +262,5 @@ TEST(BakedOpState, tryStrokeableOpConstruct) {
}
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index 6115162c8f81..c235715073f5 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -20,6 +20,8 @@
#include "renderthread/EglManager.h"
#include "tests/common/TestUtils.h"
+#include <SkImagePriv.h>
+
using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;
@@ -35,7 +37,8 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
GrContext* grContext = renderThread.getGrContext();
ASSERT_TRUE(grContext != nullptr);
- // create pairs of offscreen render targets and images until we exceed the backgroundCacheSizeLimit
+ // create pairs of offscreen render targets and images until we exceed the
+ // backgroundCacheSizeLimit
std::vector<sk_sp<SkSurface>> surfaces;
while (getCacheUsage(grContext) <= renderThread.cacheManager().getBackgroundCacheSize()) {
@@ -48,7 +51,12 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
surfaces.push_back(surface);
}
- ASSERT_TRUE(1 < surfaces.size());
+ // create an image and pin it so that we have something with a unique key in the cache
+ sk_sp<Bitmap> bitmap =
+ Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(displayInfo.w, displayInfo.h));
+ sk_sp<SkColorFilter> filter;
+ sk_sp<SkImage> image = bitmap->makeImage(&filter);
+ ASSERT_TRUE(SkImage_pinAsTexture(image.get(), grContext));
// attempt to trim all memory while we still hold strong refs
renderThread.cacheManager().trimMemory(CacheManager::TrimMemoryMode::Complete);
@@ -60,11 +68,14 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
surfaces[i].reset();
}
+ // unpin the image which should add a unique purgeable key to the cache
+ SkImage_unpinAsTexture(image.get(), grContext);
+
// verify that we have enough purgeable bytes
const size_t purgeableBytes = grContext->getResourceCachePurgeableBytes();
ASSERT_TRUE(renderThread.cacheManager().getBackgroundCacheSize() < purgeableBytes);
- // UI hidden and make sure only some got purged
+ // UI hidden and make sure only some got purged (unique should remain)
renderThread.cacheManager().trimMemory(CacheManager::TrimMemoryMode::UiHidden);
ASSERT_TRUE(0 < grContext->getResourceCachePurgeableBytes());
ASSERT_TRUE(renderThread.cacheManager().getBackgroundCacheSize() > getCacheUsage(grContext));
diff --git a/libs/hwui/tests/unit/CanvasContextTests.cpp b/libs/hwui/tests/unit/CanvasContextTests.cpp
index ef5ce0d9968e..28cff5b9b154 100644
--- a/libs/hwui/tests/unit/CanvasContextTests.cpp
+++ b/libs/hwui/tests/unit/CanvasContextTests.cpp
@@ -35,8 +35,8 @@ public:
RENDERTHREAD_TEST(CanvasContext, create) {
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, rootNode.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
ASSERT_FALSE(canvasContext->hasSurface());
diff --git a/libs/hwui/tests/unit/CanvasStateTests.cpp b/libs/hwui/tests/unit/CanvasStateTests.cpp
index c41313aebb5d..4c03811b0c96 100644
--- a/libs/hwui/tests/unit/CanvasStateTests.cpp
+++ b/libs/hwui/tests/unit/CanvasStateTests.cpp
@@ -21,14 +21,14 @@
#include "hwui/Canvas.h"
#include "utils/LinearAllocator.h"
-#include <gtest/gtest.h>
-#include <SkPath.h>
#include <SkClipOp.h>
+#include <SkPath.h>
+#include <gtest/gtest.h>
namespace android {
namespace uirenderer {
-class NullClient: public CanvasStateClient {
+class NullClient : public CanvasStateClient {
void onViewportInitialized() override {}
void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
GLuint getTargetFbo() const override { return 0; }
@@ -47,8 +47,7 @@ static bool approxEqual(const Matrix4& a, const Matrix4& b) {
TEST(CanvasState, gettersAndSetters) {
CanvasState state(sNullClient);
- state.initializeSaveStack(200, 200,
- 0, 0, 200, 200, Vector3());
+ state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
ASSERT_EQ(state.getWidth(), 200);
ASSERT_EQ(state.getHeight(), 200);
@@ -65,8 +64,7 @@ TEST(CanvasState, gettersAndSetters) {
TEST(CanvasState, simpleClipping) {
CanvasState state(sNullClient);
- state.initializeSaveStack(200, 200,
- 0, 0, 200, 200, Vector3());
+ state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
state.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(100, 100));
@@ -80,8 +78,7 @@ TEST(CanvasState, simpleClipping) {
TEST(CanvasState, complexClipping) {
CanvasState state(sNullClient);
- state.initializeSaveStack(200, 200,
- 0, 0, 200, 200, Vector3());
+ state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
state.save(SaveFlags::MatrixClip);
{
@@ -116,8 +113,7 @@ TEST(CanvasState, complexClipping) {
TEST(CanvasState, saveAndRestore) {
CanvasState state(sNullClient);
- state.initializeSaveStack(200, 200,
- 0, 0, 200, 200, Vector3());
+ state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
state.save(SaveFlags::Clip);
{
@@ -125,7 +121,7 @@ TEST(CanvasState, saveAndRestore) {
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
}
state.restore();
- ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200)); // verify restore
+ ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200)); // verify restore
Matrix4 simpleTranslate;
simpleTranslate.loadTranslate(10, 10, 0);
@@ -140,27 +136,25 @@ TEST(CanvasState, saveAndRestore) {
TEST(CanvasState, saveAndRestoreButNotTooMuch) {
CanvasState state(sNullClient);
- state.initializeSaveStack(200, 200,
- 0, 0, 200, 200, Vector3());
+ state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
- state.save(SaveFlags::Matrix); // NOTE: clip not saved
+ state.save(SaveFlags::Matrix); // NOTE: clip not saved
{
state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
}
state.restore();
- ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10)); // verify not restored
+ ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10)); // verify not restored
Matrix4 simpleTranslate;
simpleTranslate.loadTranslate(10, 10, 0);
- state.save(SaveFlags::Clip); // NOTE: matrix not saved
+ state.save(SaveFlags::Clip); // NOTE: matrix not saved
{
state.translate(10, 10, 0);
EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
}
state.restore();
- EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate)); // verify not restored
+ EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate)); // verify not restored
}
-
}
}
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index d4d7919f9eee..450bb679a45f 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
#include <SkPath.h>
#include <SkRegion.h>
+#include <gtest/gtest.h>
#include "ClipArea.h"
@@ -194,7 +194,8 @@ TEST(ClipArea, serializeIntersectedClip) {
{
auto origRectClip = area.serializeClip(allocator);
ASSERT_NE(nullptr, origRectClip);
- EXPECT_EQ(origRectClip, area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity()));
+ EXPECT_EQ(origRectClip,
+ area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity()));
}
// rect
@@ -208,11 +209,13 @@ TEST(ClipArea, serializeIntersectedClip) {
ASSERT_EQ(ClipMode::Rectangle, resolvedClip->mode);
EXPECT_EQ(Rect(100, 100, 200, 200), resolvedClip->rect);
- EXPECT_EQ(resolvedClip, area.serializeIntersectedClip(allocator, &recordedClip, translateScale))
+ EXPECT_EQ(resolvedClip,
+ area.serializeIntersectedClip(allocator, &recordedClip, translateScale))
<< "Must return previous serialization, since input is same";
ClipRect recordedClip2(Rect(100, 100));
- EXPECT_NE(resolvedClip, area.serializeIntersectedClip(allocator, &recordedClip2, translateScale))
+ EXPECT_NE(resolvedClip,
+ area.serializeIntersectedClip(allocator, &recordedClip2, translateScale))
<< "Shouldn't return previous serialization, since matrix location is different";
}
@@ -222,7 +225,8 @@ TEST(ClipArea, serializeIntersectedClip) {
area.clipRectWithTransform(Rect(200, 200), &rotate, SkRegion::kIntersect_Op);
{
ClipRect recordedClip(Rect(100, 100));
- auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, Matrix4::identity());
+ auto resolvedClip =
+ area.serializeIntersectedClip(allocator, &recordedClip, Matrix4::identity());
ASSERT_NE(nullptr, resolvedClip);
ASSERT_EQ(ClipMode::RectangleList, resolvedClip->mode);
auto clipRectList = reinterpret_cast<const ClipRectList*>(resolvedClip);
@@ -243,8 +247,9 @@ TEST(ClipArea, serializeIntersectedClip) {
Matrix4 translate10x20;
translate10x20.loadTranslate(10, 20, 0);
- auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip,
- translate10x20); // Note: only translate for now, others not handled correctly
+ auto resolvedClip = area.serializeIntersectedClip(
+ allocator, &recordedClip,
+ translate10x20); // Note: only translate for now, others not handled correctly
ASSERT_NE(nullptr, resolvedClip);
ASSERT_EQ(ClipMode::Region, resolvedClip->mode);
auto clipRegion = reinterpret_cast<const ClipRegion*>(resolvedClip);
@@ -267,7 +272,8 @@ TEST(ClipArea, serializeIntersectedClip_snap) {
ClipRect recordedClip(Rect(100.12, 100.74));
Matrix4 translateScale;
translateScale.loadTranslate(100, 100, 0);
- translateScale.scale(2, 3, 1); // recorded clip will have non-int coords, even after transform
+ translateScale.scale(2, 3,
+ 1); // recorded clip will have non-int coords, even after transform
auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
ASSERT_NE(nullptr, resolvedClip);
EXPECT_EQ(ClipMode::Rectangle, resolvedClip->mode);
@@ -343,5 +349,5 @@ TEST(ClipArea, applyTransformToRegion_rotate90) {
EXPECT_EQ(SkIRect::MakeLTRB(-4, 1, -2, 3), region.getBounds());
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index 87d897ee6a7b..f29830f0e34b 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -44,13 +44,12 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) {
// push the deferred updates to the layer
Matrix4 scaledMatrix;
scaledMatrix.loadScale(0.5, 0.5, 0.0);
- layerUpdater->updateLayer(true, scaledMatrix.data);
+ layerUpdater->updateLayer(true, scaledMatrix.data, HAL_DATASPACE_UNKNOWN);
if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
glLayer->setRenderTarget(GL_TEXTURE_EXTERNAL_OES);
}
-
// the backing layer should now have all the properties applied.
if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
diff --git a/libs/hwui/tests/unit/FatVectorTests.cpp b/libs/hwui/tests/unit/FatVectorTests.cpp
index 64b0ba13562d..8523e6c9e973 100644
--- a/libs/hwui/tests/unit/FatVectorTests.cpp
+++ b/libs/hwui/tests/unit/FatVectorTests.cpp
@@ -22,12 +22,11 @@
using namespace android;
using namespace android::uirenderer;
-template<class VectorType>
+template <class VectorType>
static bool allocationIsInternal(VectorType& v) {
// allocation array (from &v[0] to &v[0] + v.capacity) is
// located within the vector object itself
- return (char*)(&v) <= (char*)(&v[0])
- && (char*)(&v + 1) >= (char*)(&v[0] + v.capacity());
+ return (char*)(&v) <= (char*)(&v[0]) && (char*)(&v + 1) >= (char*)(&v[0] + v.capacity());
}
TEST(FatVector, baseline) {
diff --git a/libs/hwui/tests/unit/FatalTestCanvas.h b/libs/hwui/tests/unit/FatalTestCanvas.h
index 03d94964ac76..9693ce7b6784 100644
--- a/libs/hwui/tests/unit/FatalTestCanvas.h
+++ b/libs/hwui/tests/unit/FatalTestCanvas.h
@@ -16,15 +16,14 @@
#pragma once
-#include <gtest/gtest.h>
#include <SkCanvas.h>
+#include <gtest/gtest.h>
namespace {
class TestCanvasBase : public SkCanvas {
public:
- TestCanvasBase(int width, int height) : SkCanvas(width, height) {
- }
+ TestCanvasBase(int width, int height) : SkCanvas(width, height) {}
void onDrawAnnotation(const SkRect&, const char key[], SkData* value) {
ADD_FAILURE() << "onDrawAnnotation not expected in this test";
}
@@ -32,35 +31,33 @@ public:
ADD_FAILURE() << "onDrawDRRect not expected in this test";
}
void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint) {
+ const SkPaint& paint) {
ADD_FAILURE() << "onDrawText not expected in this test";
}
void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
- const SkPaint& paint) {
+ const SkPaint& paint) {
ADD_FAILURE() << "onDrawPosText not expected in this test";
}
void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+ const SkPaint& paint) {
ADD_FAILURE() << "onDrawPosTextH not expected in this test";
}
void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
- const SkMatrix* matrix, const SkPaint& paint) {
+ const SkMatrix* matrix, const SkPaint& paint) {
ADD_FAILURE() << "onDrawTextOnPath not expected in this test";
}
void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
- const SkRect* cullRect, const SkPaint& paint) {
+ const SkRect* cullRect, const SkPaint& paint) {
ADD_FAILURE() << "onDrawTextRSXform not expected in this test";
}
void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
ADD_FAILURE() << "onDrawTextBlob not expected in this test";
}
void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
- SkBlendMode, const SkPaint& paint) {
+ SkBlendMode, const SkPaint& paint) {
ADD_FAILURE() << "onDrawPatch not expected in this test";
}
- void onDrawPaint(const SkPaint&) {
- ADD_FAILURE() << "onDrawPaint not expected in this test";
- }
+ void onDrawPaint(const SkPaint&) { ADD_FAILURE() << "onDrawPaint not expected in this test"; }
void onDrawRect(const SkRect&, const SkPaint&) {
ADD_FAILURE() << "onDrawRect not expected in this test";
}
@@ -71,7 +68,7 @@ public:
ADD_FAILURE() << "onDrawOval not expected in this test";
}
void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
- const SkPaint&) {
+ const SkPaint&) {
ADD_FAILURE() << "onDrawArc not expected in this test";
}
void onDrawRRect(const SkRRect&, const SkPaint&) {
@@ -84,7 +81,7 @@ public:
ADD_FAILURE() << "onDrawVertices not expected in this test";
}
void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int count,
- SkBlendMode, const SkRect* cull, const SkPaint*) {
+ SkBlendMode, const SkRect* cull, const SkPaint*) {
ADD_FAILURE() << "onDrawAtlas not expected in this test";
}
void onDrawPath(const SkPath&, const SkPaint&) {
@@ -94,29 +91,29 @@ public:
ADD_FAILURE() << "onDrawImage not expected in this test";
}
void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
- SrcRectConstraint) {
+ SrcRectConstraint) {
ADD_FAILURE() << "onDrawImageRect not expected in this test";
}
void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, const SkPaint*) {
ADD_FAILURE() << "onDrawImageNine not expected in this test";
}
void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
- const SkPaint*) {
+ const SkPaint*) {
ADD_FAILURE() << "onDrawImageLattice not expected in this test";
}
void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*) {
ADD_FAILURE() << "onDrawBitmap not expected in this test";
}
void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
- SrcRectConstraint) {
+ SrcRectConstraint) {
ADD_FAILURE() << "onDrawBitmapRect not expected in this test";
}
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
- const SkPaint*) {
+ const SkPaint*) {
ADD_FAILURE() << "onDrawBitmapNine not expected in this test";
}
void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
- const SkPaint*) {
+ const SkPaint*) {
ADD_FAILURE() << "onDrawBitmapLattice not expected in this test";
}
void onClipRRect(const SkRRect& rrect, SkClipOp, ClipEdgeStyle) {
@@ -128,14 +125,11 @@ public:
void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {
ADD_FAILURE() << "onClipRegion not expected in this test";
}
- void onDiscard() {
- ADD_FAILURE() << "onDiscard not expected in this test";
- }
+ void onDiscard() { ADD_FAILURE() << "onDiscard not expected in this test"; }
void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) {
ADD_FAILURE() << "onDrawPicture not expected in this test";
}
- int mDrawCounter = 0; //counts how may draw calls of any kind were made to this canvas
+ int mDrawCounter = 0; // counts how may draw calls of any kind were made to this canvas
};
-
} \ No newline at end of file
diff --git a/libs/hwui/tests/unit/FontRendererTests.cpp b/libs/hwui/tests/unit/FontRendererTests.cpp
index ee202367d73e..c78f131ce2ce 100644
--- a/libs/hwui/tests/unit/FontRendererTests.cpp
+++ b/libs/hwui/tests/unit/FontRendererTests.cpp
@@ -40,16 +40,16 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, renderDropShadow) {
std::vector<float> positions;
float totalAdvance;
Rect bounds;
- TestUtils::layoutTextUnscaled(paint, "This is a test",
- &glyphs, &positions, &totalAdvance, &bounds);
+ TestUtils::layoutTextUnscaled(paint, "This is a test", &glyphs, &positions, &totalAdvance,
+ &bounds);
for (int radius : {28, 20, 2}) {
- auto result = fontRenderer.renderDropShadow(&paint, glyphs.data(), glyphs.size(),
- radius, positions.data());
+ auto result = fontRenderer.renderDropShadow(&paint, glyphs.data(), glyphs.size(), radius,
+ positions.data());
ASSERT_NE(nullptr, result.image);
EXPECT_FALSE(isZero(result.image, result.width * result.height));
- EXPECT_LE(bounds.getWidth() + radius * 2, (int) result.width);
- EXPECT_LE(bounds.getHeight() + radius * 2, (int) result.height);
+ EXPECT_LE(bounds.getWidth() + radius * 2, (int)result.width);
+ EXPECT_LE(bounds.getHeight() + radius * 2, (int)result.height);
delete result.image;
}
}
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index fcdd814bb63e..4eb77514f4ae 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -30,7 +30,7 @@
namespace android {
namespace uirenderer {
-const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
+const FrameBuilder::LightGeometry sLightGeometry = {{100, 100, 100}, 50};
/**
* Virtual class implemented by each test to redirect static operation / state transitions to
@@ -56,23 +56,21 @@ public:
virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) {
ADD_FAILURE() << "Layer repaint not expected in this test";
}
- virtual void endLayer() {
- ADD_FAILURE() << "Layer updates not expected in this test";
- }
+ virtual void endLayer() { ADD_FAILURE() << "Layer updates not expected in this test"; }
virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {}
virtual void endFrame(const Rect& repaintRect) {}
- // define virtual defaults for single draw methods
-#define X(Type) \
+// define virtual defaults for single draw methods
+#define X(Type) \
virtual void on##Type(const Type&, const BakedOpState&) { \
- ADD_FAILURE() << #Type " not expected in this test"; \
+ ADD_FAILURE() << #Type " not expected in this test"; \
}
MAP_RENDERABLE_OPS(X)
#undef X
- // define virtual defaults for merged draw methods
-#define X(Type) \
- virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \
+// define virtual defaults for merged draw methods
+#define X(Type) \
+ virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \
ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \
}
MAP_MERGEABLE_OPS(X)
@@ -90,18 +88,18 @@ protected:
*/
class TestDispatcher {
public:
- // define single op methods, which redirect to TestRendererBase
-#define X(Type) \
+// define single op methods, which redirect to TestRendererBase
+#define X(Type) \
static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \
- renderer.on##Type(op, state); \
+ renderer.on##Type(op, state); \
}
MAP_RENDERABLE_OPS(X);
#undef X
- // define merged op methods, which redirect to TestRendererBase
-#define X(Type) \
+// define merged op methods, which redirect to TestRendererBase
+#define X(Type) \
static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \
- renderer.onMerged##Type##s(opList); \
+ renderer.onMerged##Type##s(opList); \
}
MAP_MERGEABLE_OPS(X);
#undef X
@@ -123,24 +121,22 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simple) {
void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
EXPECT_EQ(2, mIndex++);
}
- void endFrame(const Rect& repaintRect) override {
- EXPECT_EQ(3, mIndex++);
- }
+ void endFrame(const Rect& repaintRect) override { EXPECT_EQ(3, mIndex++); }
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25));
- canvas.drawRect(0, 0, 100, 200, SkPaint());
- canvas.drawBitmap(*bitmap, 10, 10, nullptr);
- });
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25));
+ canvas.drawRect(0, 0, 100, 200, SkPaint());
+ canvas.drawBitmap(*bitmap, 10, 10, nullptr);
+ });
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end
+ EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleStroke) {
@@ -156,14 +152,14 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleStroke) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- SkPaint strokedPaint;
- strokedPaint.setStrokeWidth(10);
- canvas.drawPoint(50, 50, strokedPaint);
- });
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ SkPaint strokedPaint;
+ strokedPaint.setStrokeWidth(10);
+ canvas.drawPoint(50, 50, strokedPaint);
+ });
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SimpleStrokeTestRenderer renderer;
@@ -171,7 +167,6 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleStroke) {
EXPECT_EQ(1, renderer.getIndex());
}
-
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, arcStrokeClip) {
class ArcStrokeClipTestRenderer : public TestRendererBase {
public:
@@ -184,15 +179,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, arcStrokeClip) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.clipRect(25, 25, 175, 175, SkClipOp::kIntersect);
- SkPaint aaPaint;
- aaPaint.setAntiAlias(true);
- canvas.drawArc(25, 25, 175, 175, 40, 180, true, aaPaint);
- });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.clipRect(25, 25, 175, 175, SkClipOp::kIntersect);
+ SkPaint aaPaint;
+ aaPaint.setAntiAlias(true);
+ canvas.drawArc(25, 25, 175, 175, 40, 180, true, aaPaint);
+ });
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
ArcStrokeClipTestRenderer renderer;
@@ -201,15 +196,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, arcStrokeClip) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleRejection) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
+ auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [](RenderProperties& props,
+ RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); // intersection should be empty
+ canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); // intersection should be empty
canvas.drawRect(0, 0, 400, 400, SkPaint());
canvas.restore();
});
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
FailRenderer renderer;
@@ -228,30 +223,30 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleBatching) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
-
- sk_sp<Bitmap> bitmap(TestUtils::createBitmap(10, 10,
- kAlpha_8_SkColorType)); // Disable merging by using alpha 8 bitmap
-
- // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
- // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
- canvas.save(SaveFlags::MatrixClip);
- for (int i = 0; i < LOOPS; i++) {
- canvas.translate(0, 10);
- canvas.drawRect(0, 0, 10, 10, SkPaint());
- canvas.drawBitmap(*bitmap, 5, 0, nullptr);
- }
- canvas.restore();
- });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(
+ 10, 10,
+ kAlpha_8_SkColorType)); // Disable merging by using alpha 8 bitmap
+
+ // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
+ // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
+ canvas.save(SaveFlags::MatrixClip);
+ for (int i = 0; i < LOOPS; i++) {
+ canvas.translate(0, 10);
+ canvas.drawRect(0, 0, 10, 10, SkPaint());
+ canvas.drawBitmap(*bitmap, 5, 0, nullptr);
+ }
+ canvas.restore();
+ });
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SimpleBatchingTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(2 * LOOPS, renderer.getIndex())
- << "Expect number of ops = 2 * loop count";
+ EXPECT_EQ(2 * LOOPS, renderer.getIndex()) << "Expect number of ops = 2 * loop count";
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNode_translateClip) {
@@ -261,19 +256,19 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNode_translateClip) {
EXPECT_EQ(0, mIndex++);
EXPECT_EQ(Rect(5, 10, 55, 60), state.computedState.clippedBounds);
EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom,
- state.computedState.clipSideFlags);
+ state.computedState.clipSideFlags);
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 100, 100, SkPaint());
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
- frameBuilder.deferRenderNode(5, 10, Rect(50, 50), // translate + clip node
- *TestUtils::getSyncedNode(node));
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
+ frameBuilder.deferRenderNode(5, 10, Rect(50, 50), // translate + clip node
+ *TestUtils::getSyncedNode(node));
DeferRenderNodeTranslateClipTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
@@ -287,27 +282,27 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNodeScene) {
const Rect& clippedBounds = state.computedState.clippedBounds;
Matrix4 expected;
switch (mIndex++) {
- case 0:
- // background - left side
- EXPECT_EQ(Rect(600, 100, 700, 500), clippedBounds);
- expected.loadTranslate(100, 100, 0);
- break;
- case 1:
- // background - top side
- EXPECT_EQ(Rect(100, 400, 600, 500), clippedBounds);
- expected.loadTranslate(100, 100, 0);
- break;
- case 2:
- // content
- EXPECT_EQ(Rect(100, 100, 700, 500), clippedBounds);
- expected.loadTranslate(-50, -50, 0);
- break;
- case 3:
- // overlay
- EXPECT_EQ(Rect(0, 0, 800, 200), clippedBounds);
- break;
- default:
- ADD_FAILURE() << "Too many rects observed";
+ case 0:
+ // background - left side
+ EXPECT_EQ(Rect(600, 100, 700, 500), clippedBounds);
+ expected.loadTranslate(100, 100, 0);
+ break;
+ case 1:
+ // background - top side
+ EXPECT_EQ(Rect(100, 400, 600, 500), clippedBounds);
+ expected.loadTranslate(100, 100, 0);
+ break;
+ case 2:
+ // content
+ EXPECT_EQ(Rect(100, 100, 700, 500), clippedBounds);
+ expected.loadTranslate(-50, -50, 0);
+ break;
+ case 3:
+ // overlay
+ EXPECT_EQ(Rect(0, 0, 800, 200), clippedBounds);
+ break;
+ default:
+ ADD_FAILURE() << "Too many rects observed";
}
EXPECT_EQ(expected, state.computedState.transform);
}
@@ -318,31 +313,32 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNodeScene) {
transparentPaint.setAlpha(128);
// backdrop
- nodes.push_back(TestUtils::createNode<RecordingCanvas>(100, 100, 700, 500, // 600x400
+ nodes.push_back(TestUtils::createNode<RecordingCanvas>(
+ 100, 100, 700, 500, // 600x400
[&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 600, 400, transparentPaint);
- }));
+ canvas.drawRect(0, 0, 600, 400, transparentPaint);
+ }));
// content
- Rect contentDrawBounds(150, 150, 650, 450); // 500x300
- nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600,
- [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 800, 600, transparentPaint);
- }));
+ Rect contentDrawBounds(150, 150, 650, 450); // 500x300
+ nodes.push_back(TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 800, 600, [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 800, 600, transparentPaint);
+ }));
// overlay
- nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600,
- [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 800, 200, transparentPaint);
- }));
+ nodes.push_back(TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 800, 600, [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 800, 200, transparentPaint);
+ }));
for (auto& node : nodes) {
TestUtils::syncHierarchyPropertiesAndDisplayList(node);
}
{
- FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
DeferRenderNodeSceneTestRenderer renderer;
@@ -363,8 +359,8 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNodeScene) {
{
// Validate no crashes if any nodes are missing DisplayLists
- FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
FailRenderer renderer;
@@ -396,24 +392,22 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_withFbo0) {
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
EXPECT_EQ(0, mIndex++);
}
- void endFrame(const Rect& repaintRect) override {
- EXPECT_EQ(1, mIndex++);
- }
+ void endFrame(const Rect& repaintRect) override { EXPECT_EQ(1, mIndex++); }
};
- auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- // no drawn content
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 10, 10, 110, 110, [](RenderProperties& props, RecordingCanvas& canvas) {
+ // no drawn content
+ });
// Draw, but pass node without draw content, so no work is done for primary frame
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
EmptyWithFbo0TestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex()) << "No drawing content produced,"
- " but fbo0 update lifecycle should still be observed";
+ " but fbo0 update lifecycle should still be observed";
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_rects) {
@@ -425,17 +419,17 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_rects) {
<< "Last rect should occlude others.";
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 200, 200, SkPaint());
- canvas.drawRect(0, 0, 200, 200, SkPaint());
- canvas.drawRect(10, 10, 190, 190, SkPaint());
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.drawRect(10, 10, 190, 190, SkPaint());
+ });
// Damage (and therefore clip) is same as last draw, subset of renderable area.
// This means last op occludes other contents, and they'll be rejected to avoid overdraw.
- FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 190, 190), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 190, 190), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
EXPECT_EQ(3u, node->getDisplayList()->getOps().size())
@@ -447,38 +441,38 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_rects) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_bitmaps) {
- static sk_sp<Bitmap> opaqueBitmap(TestUtils::createBitmap(50, 50,
- SkColorType::kRGB_565_SkColorType));
- static sk_sp<Bitmap> transpBitmap(TestUtils::createBitmap(50, 50,
- SkColorType::kAlpha_8_SkColorType));
+ static sk_sp<Bitmap> opaqueBitmap(
+ TestUtils::createBitmap(50, 50, SkColorType::kRGB_565_SkColorType));
+ static sk_sp<Bitmap> transpBitmap(
+ TestUtils::createBitmap(50, 50, SkColorType::kAlpha_8_SkColorType));
class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase {
public:
void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
- switch(mIndex++) {
- case 0:
- EXPECT_EQ(opaqueBitmap.get(), op.bitmap);
- break;
- case 1:
- EXPECT_EQ(transpBitmap.get(), op.bitmap);
- break;
- default:
- ADD_FAILURE() << "Only two ops expected.";
+ switch (mIndex++) {
+ case 0:
+ EXPECT_EQ(opaqueBitmap.get(), op.bitmap);
+ break;
+ case 1:
+ EXPECT_EQ(transpBitmap.get(), op.bitmap);
+ break;
+ default:
+ ADD_FAILURE() << "Only two ops expected.";
}
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 50, 50,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 50, 50, SkPaint());
- canvas.drawRect(0, 0, 50, 50, SkPaint());
- canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
-
- // only the below draws should remain, since they're
- canvas.drawBitmap(*opaqueBitmap, 0, 0, nullptr);
- canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
- });
- FrameBuilder frameBuilder(SkRect::MakeWH(50, 50), 50, 50,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 50, 50, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 50, 50, SkPaint());
+ canvas.drawRect(0, 0, 50, 50, SkPaint());
+ canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
+
+ // only the below draws should remain, since they're
+ canvas.drawBitmap(*opaqueBitmap, 0, 0, nullptr);
+ canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
+ });
+ FrameBuilder frameBuilder(SkRect::MakeWH(50, 50), 50, 50, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
EXPECT_EQ(5u, node->getDisplayList()->getOps().size())
@@ -498,32 +492,32 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clippedMerging) {
EXPECT_EQ(4u, opList.count);
EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip);
EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right,
- opList.clipSideFlags);
+ opList.clipSideFlags);
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20));
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20));
- // left side clipped (to inset left half)
- canvas.clipRect(10, 0, 50, 100, SkClipOp::kReplace_deprecated);
- canvas.drawBitmap(*bitmap, 0, 40, nullptr);
+ // left side clipped (to inset left half)
+ canvas.clipRect(10, 0, 50, 100, SkClipOp::kReplace_deprecated);
+ canvas.drawBitmap(*bitmap, 0, 40, nullptr);
- // top side clipped (to inset top half)
- canvas.clipRect(0, 10, 100, 50, SkClipOp::kReplace_deprecated);
- canvas.drawBitmap(*bitmap, 40, 0, nullptr);
+ // top side clipped (to inset top half)
+ canvas.clipRect(0, 10, 100, 50, SkClipOp::kReplace_deprecated);
+ canvas.drawBitmap(*bitmap, 40, 0, nullptr);
- // right side clipped (to inset right half)
- canvas.clipRect(50, 0, 90, 100, SkClipOp::kReplace_deprecated);
- canvas.drawBitmap(*bitmap, 80, 40, nullptr);
+ // right side clipped (to inset right half)
+ canvas.clipRect(50, 0, 90, 100, SkClipOp::kReplace_deprecated);
+ canvas.drawBitmap(*bitmap, 80, 40, nullptr);
- // bottom not clipped, just abutting (inset bottom half)
- canvas.clipRect(0, 50, 100, 90, SkClipOp::kReplace_deprecated);
- canvas.drawBitmap(*bitmap, 40, 70, nullptr);
- });
+ // bottom not clipped, just abutting (inset bottom half)
+ canvas.clipRect(0, 50, 100, 90, SkClipOp::kReplace_deprecated);
+ canvas.drawBitmap(*bitmap, 40, 70, nullptr);
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
ClippedMergingTestRenderer renderer;
@@ -536,23 +530,22 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, regionClipStopsMerge) {
public:
void onTextOp(const TextOp& op, const BakedOpState& state) override { mIndex++; }
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- SkPath path;
- path.addCircle(200, 200, 200, SkPath::kCW_Direction);
- canvas.save(SaveFlags::MatrixClip);
- canvas.clipPath(&path, SkClipOp::kIntersect);
- SkPaint paint;
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- paint.setAntiAlias(true);
- paint.setTextSize(50);
- TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
- TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200);
- canvas.restore();
- });
-
- FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 400, [](RenderProperties& props, RecordingCanvas& canvas) {
+ SkPath path;
+ path.addCircle(200, 200, 200, SkPath::kCW_Direction);
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.clipPath(&path, SkClipOp::kIntersect);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(50);
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200);
+ canvas.restore();
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
RegionClipStopsMergeTestRenderer renderer;
@@ -572,17 +565,16 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textMerging) {
EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags);
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
- [](RenderProperties& props, RecordingCanvas& canvas) {
+ auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, [](RenderProperties& props,
+ RecordingCanvas& canvas) {
SkPaint paint;
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setAntiAlias(true);
paint.setTextSize(50);
- TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
- TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
});
- FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
TextMergingTestRenderer renderer;
@@ -603,30 +595,27 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStrikethrough) {
EXPECT_EQ(5u, opList.count);
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 2000,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- SkPaint textPaint;
- textPaint.setAntiAlias(true);
- textPaint.setTextSize(20);
- textPaint.setFlags(textPaint.getFlags() | SkPaint::kStrikeThruText_ReserveFlag);
- textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- for (int i = 0; i < LOOPS; i++) {
- TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
- }
- });
-
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 2000), 200, 2000,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 2000, [](RenderProperties& props, RecordingCanvas& canvas) {
+ SkPaint textPaint;
+ textPaint.setAntiAlias(true);
+ textPaint.setTextSize(20);
+ textPaint.setFlags(textPaint.getFlags() | SkPaint::kStrikeThruText_ReserveFlag);
+ for (int i = 0; i < LOOPS; i++) {
+ TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
+ }
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 2000), 200, 2000, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
TextStrikethroughTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
- EXPECT_EQ(2 * LOOPS, renderer.getIndex())
- << "Expect number of ops = 2 * loop count";
+ EXPECT_EQ(2 * LOOPS, renderer.getIndex()) << "Expect number of ops = 2 * loop count";
}
-static auto styles = {
- SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style };
+static auto styles = {SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style};
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStyle) {
class TextStyleTestRenderer : public TestRendererBase {
@@ -659,23 +648,22 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStyle) {
EXPECT_EQ(stroke, outsetFill);
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- SkPaint paint;
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- paint.setAntiAlias(true);
- paint.setTextSize(50);
- paint.setStrokeWidth(10);
-
- // draw 3 copies of the same text overlapping, each with a different style.
- // They'll get merged, but with
- for (auto style : styles) {
- paint.setStyle(style);
- TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
- }
- });
- FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 400, [](RenderProperties& props, RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(50);
+ paint.setStrokeWidth(10);
+
+ // draw 3 copies of the same text overlapping, each with a different style.
+ // They'll get merged, but with
+ for (auto style : styles) {
+ paint.setStyle(style);
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
+ }
+ });
+ FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
TextStyleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
@@ -696,19 +684,19 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_clipLocalMatrix) {
}
};
- auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
- SkMatrix::MakeTrans(5, 5));
+ auto layerUpdater =
+ TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5));
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(50, 50, 150, 150, SkClipOp::kIntersect);
- canvas.drawLayer(layerUpdater.get());
- canvas.restore();
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.clipRect(50, 50, 150, 150, SkClipOp::kIntersect);
+ canvas.drawLayer(layerUpdater.get());
+ canvas.restore();
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
TextureLayerClipLocalMatrixTestRenderer renderer;
@@ -728,19 +716,19 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_combineMatrices) {
}
};
- auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
- SkMatrix::MakeTrans(5, 5));
+ auto layerUpdater =
+ TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5));
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.save(SaveFlags::MatrixClip);
- canvas.translate(30, 40);
- canvas.drawLayer(layerUpdater.get());
- canvas.restore();
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.translate(30, 40);
+ canvas.drawLayer(layerUpdater.get());
+ canvas.restore();
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
TextureLayerCombineMatricesTestRenderer renderer;
@@ -749,20 +737,20 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_combineMatrices) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_reject) {
- auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
- SkMatrix::MakeTrans(5, 5));
+ auto layerUpdater =
+ TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5));
EXPECT_EQ(Layer::Api::OpenGL, layerUpdater->backingLayer()->getApi());
GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
- glLayer->setRenderTarget(GL_NONE); // Should be rejected
+ glLayer->setRenderTarget(GL_NONE); // Should be rejected
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.drawLayer(layerUpdater.get());
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawLayer(layerUpdater.get());
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
FailRenderer renderer;
@@ -779,14 +767,14 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, functor_reject) {
Functor noopFunctor;
// 1 million pixel tall view, scrolled down 80%
- auto scrolledFunctorView = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 1000000,
- [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.translate(0, -800000);
- canvas.callDrawGLFunction(&noopFunctor, nullptr);
- });
-
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ auto scrolledFunctorView = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 1000000, [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.translate(0, -800000);
+ canvas.callDrawGLFunction(&noopFunctor, nullptr);
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(scrolledFunctorView));
FunctorTestRenderer renderer;
@@ -804,14 +792,14 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferColorOp_unbounded) {
}
};
- auto unclippedColorView = TestUtils::createNode<RecordingCanvas>(0, 0, 10, 10,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setClipToBounds(false);
- canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
- });
+ auto unclippedColorView = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 10, 10, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setClipToBounds(false);
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(unclippedColorView));
ColorTestRenderer renderer;
@@ -823,42 +811,42 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) {
class RenderNodeTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
- switch(mIndex++) {
- case 0:
- EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds);
- EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
- break;
- case 1:
- EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds);
- EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
- break;
- default:
- ADD_FAILURE();
+ switch (mIndex++) {
+ case 0:
+ EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds);
+ EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
+ break;
+ case 1:
+ EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds);
+ EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
+ break;
+ default:
+ ADD_FAILURE();
}
}
};
- auto child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
-
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [&child](RenderProperties& props, RecordingCanvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorDKGRAY);
- canvas.drawRect(0, 0, 200, 200, paint);
-
- canvas.save(SaveFlags::MatrixClip);
- canvas.translate(40, 40);
- canvas.drawRenderNode(child.get());
- canvas.restore();
- });
-
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ auto child = TestUtils::createNode<RecordingCanvas>(
+ 10, 10, 110, 110, [](RenderProperties& props, RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
+
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [&child](RenderProperties& props, RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(0, 0, 200, 200, paint);
+
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.translate(40, 40);
+ canvas.drawRenderNode(child.get());
+ canvas.restore();
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
RenderNodeTestRenderer renderer;
@@ -877,15 +865,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clipped) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- sk_sp<Bitmap> bitmap(TestUtils::createBitmap(200, 200));
- canvas.drawBitmap(*bitmap, 0, 0, nullptr);
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(200, 200));
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ });
// clip to small area, should see in receiver
- FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 20, 30, 40), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 20, 30, 40), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
ClippedTestRenderer renderer;
@@ -901,9 +889,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_simple) {
EXPECT_EQ(180u, height);
return nullptr;
}
- void endLayer() override {
- EXPECT_EQ(2, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(2, mIndex++); }
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(1, mIndex++);
EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds);
@@ -926,15 +912,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_simple) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer);
- canvas.drawRect(10, 10, 190, 190, SkPaint());
- canvas.restore();
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer);
+ canvas.drawRect(10, 10, 190, 190, SkPaint());
+ canvas.restore();
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SaveLayerSimpleTestRenderer renderer;
@@ -955,13 +941,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_nested) {
if (index == 0) {
EXPECT_EQ(400u, width);
EXPECT_EQ(400u, height);
- return (OffscreenBuffer*) 0x400;
+ return (OffscreenBuffer*)0x400;
} else if (index == 3) {
EXPECT_EQ(800u, width);
EXPECT_EQ(800u, height);
- return (OffscreenBuffer*) 0x800;
- } else { ADD_FAILURE(); }
- return (OffscreenBuffer*) nullptr;
+ return (OffscreenBuffer*)0x800;
+ } else {
+ ADD_FAILURE();
+ }
+ return (OffscreenBuffer*)nullptr;
}
void endLayer() override {
int index = mIndex++;
@@ -970,26 +958,28 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_nested) {
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
EXPECT_EQ(7, mIndex++);
}
- void endFrame(const Rect& repaintRect) override {
- EXPECT_EQ(9, mIndex++);
- }
+ void endFrame(const Rect& repaintRect) override { EXPECT_EQ(9, mIndex++); }
void onRectOp(const RectOp& op, const BakedOpState& state) override {
const int index = mIndex++;
if (index == 1) {
- EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect
+ EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect
} else if (index == 4) {
- EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect
- } else { ADD_FAILURE(); }
+ EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect
+ } else {
+ ADD_FAILURE();
+ }
}
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
const int index = mIndex++;
if (index == 5) {
EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle);
- EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer
+ EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer
} else if (index == 8) {
EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle);
- EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer
- } else { ADD_FAILURE(); }
+ EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer
+ } else {
+ ADD_FAILURE();
+ }
}
void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
const int index = mIndex++;
@@ -998,26 +988,26 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_nested) {
EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer);
} else if (index == 11) {
EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer);
- } else { ADD_FAILURE(); }
- }
- };
-
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 800, 800,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer);
- {
- canvas.drawRect(0, 0, 800, 800, SkPaint());
- canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer);
- {
- canvas.drawRect(0, 0, 400, 400, SkPaint());
+ } else {
+ ADD_FAILURE();
}
- canvas.restore();
}
- canvas.restore();
- });
+ };
- FrameBuilder frameBuilder(SkRect::MakeWH(800, 800), 800, 800,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 800, 800, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer);
+ {
+ canvas.drawRect(0, 0, 800, 800, SkPaint());
+ canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer);
+ { canvas.drawRect(0, 0, 400, 400, SkPaint()); }
+ canvas.restore();
+ }
+ canvas.restore();
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(800, 800), 800, 800, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SaveLayerNestedTestRenderer renderer;
@@ -1026,21 +1016,21 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_nested) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_contentRejection) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect);
- canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer);
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect);
+ canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer);
- // draw within save layer may still be recorded, but shouldn't be drawn
- canvas.drawRect(200, 200, 400, 400, SkPaint());
+ // draw within save layer may still be recorded, but shouldn't be drawn
+ canvas.drawRect(200, 200, 400, 400, SkPaint());
- canvas.restore();
- canvas.restore();
- });
+ canvas.restore();
+ canvas.restore();
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
FailRenderer renderer;
@@ -1077,15 +1067,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_simple) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
- canvas.drawRect(0, 0, 200, 200, SkPaint());
- canvas.restore();
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.restore();
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SaveLayerUnclippedSimpleTestRenderer renderer;
@@ -1110,16 +1100,16 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_round) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out
- 128, (SaveFlags::Flags)(0));
+ auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [](RenderProperties& props,
+ RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out
+ 128, (SaveFlags::Flags)(0));
canvas.drawRect(0, 0, 200, 200, SkPaint());
canvas.restore();
});
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SaveLayerUnclippedRoundTestRenderer renderer;
@@ -1162,21 +1152,21 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_mergedClears)
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
-
- int restoreTo = canvas.save(SaveFlags::MatrixClip);
- canvas.scale(2, 2);
- canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip);
- canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip);
- canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip);
- canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip);
- canvas.drawRect(0, 0, 100, 100, SkPaint());
- canvas.restoreToCount(restoreTo);
- });
-
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+
+ int restoreTo = canvas.save(SaveFlags::MatrixClip);
+ canvas.scale(2, 2);
+ canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip);
+ canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip);
+ canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip);
+ canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip);
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ canvas.restoreToCount(restoreTo);
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SaveLayerUnclippedMergedClearsTestRenderer renderer;
@@ -1209,17 +1199,17 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- // save smaller than clip, so we get unclipped behavior
- canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
- canvas.drawRect(0, 0, 200, 200, SkPaint());
- canvas.restore();
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ // save smaller than clip, so we get unclipped behavior
+ canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.restore();
+ });
// draw with partial screen dirty, and assert we see that rect later
- FrameBuilder frameBuilder(SkRect::MakeLTRB(50, 50, 150, 150), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SaveLayerUnclippedClearClipTestRenderer renderer;
@@ -1228,17 +1218,17 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_reject) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- // unclipped savelayer + rect both in area that won't intersect with dirty
- canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0));
- canvas.drawRect(100, 100, 200, 200, SkPaint());
- canvas.restore();
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ // unclipped savelayer + rect both in area that won't intersect with dirty
+ canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0));
+ canvas.drawRect(100, 100, 200, 200, SkPaint());
+ canvas.restore();
+ });
// draw with partial screen dirty that doesn't intersect with savelayer
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
FailRenderer renderer;
@@ -1253,7 +1243,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_complex) {
class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
- EXPECT_EQ(0, mIndex++); // savelayer first
+ EXPECT_EQ(0, mIndex++); // savelayer first
return (OffscreenBuffer*)0xabcd;
}
void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
@@ -1275,9 +1265,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_complex) {
int index = mIndex++;
EXPECT_TRUE(index == 4 || index == 10);
}
- void endLayer() override {
- EXPECT_EQ(5, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(5, mIndex++); }
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
EXPECT_EQ(6, mIndex++);
}
@@ -1285,28 +1273,27 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_complex) {
EXPECT_EQ(9, mIndex++);
EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
}
- void endFrame(const Rect& repaintRect) override {
- EXPECT_EQ(11, mIndex++);
- }
+ void endFrame(const Rect& repaintRect) override { EXPECT_EQ(11, mIndex++); }
void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
EXPECT_EQ(12, mIndex++);
EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer);
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 600, 600, // 500x500 triggers clipping
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 600, 600, // 500x500 triggers clipping
[](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped
- canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped
- canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped
- canvas.drawRect(200, 200, 300, 300, SkPaint());
- canvas.restore();
- canvas.restore();
- canvas.restore();
- });
-
- FrameBuilder frameBuilder(SkRect::MakeWH(600, 600), 600, 600,
- sLightGeometry, Caches::getInstance());
+ canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped
+ canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped
+ canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped
+ canvas.drawRect(200, 200, 300, 300, SkPaint());
+ canvas.restore();
+ canvas.restore();
+ canvas.restore();
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(600, 600), 600, 600, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
SaveLayerUnclippedComplexTestRenderer renderer;
@@ -1332,27 +1319,23 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_simple) {
EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect())
<< "Damage rect should be used to clip layer content";
}
- void endLayer() override {
- EXPECT_EQ(2, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(2, mIndex++); }
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
EXPECT_EQ(3, mIndex++);
}
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(4, mIndex++);
}
- void endFrame(const Rect& repaintRect) override {
- EXPECT_EQ(5, mIndex++);
- }
+ void endFrame(const Rect& repaintRect) override { EXPECT_EQ(5, mIndex++); }
};
- auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- props.mutateLayerProperties().setType(LayerType::RenderLayer);
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 10, 10, 110, 110, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
OffscreenBuffer** layerHandle = node->getLayerHandle();
// create RenderNode's layer here in same way prepareTree would
@@ -1362,11 +1345,11 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_simple) {
auto syncedNode = TestUtils::getSyncedNode(node);
// only enqueue partial damage
- LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferLayers(layerUpdateQueue);
frameBuilder.deferRenderNode(*syncedNode);
@@ -1388,7 +1371,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) {
class HwLayerComplexTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
- EXPECT_EQ(3, mIndex++); // savelayer first
+ EXPECT_EQ(3, mIndex++); // savelayer first
return (OffscreenBuffer*)0xabcd;
}
void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
@@ -1401,7 +1384,9 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) {
// starting outer layer
EXPECT_EQ(200u, offscreenBuffer->viewportWidth);
EXPECT_EQ(200u, offscreenBuffer->viewportHeight);
- } else { ADD_FAILURE(); }
+ } else {
+ ADD_FAILURE();
+ }
}
void onRectOp(const RectOp& op, const BakedOpState& state) override {
int index = mIndex++;
@@ -1411,7 +1396,9 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) {
} else if (index == 7) {
// outer layer's rect (grey)
EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
- } else { ADD_FAILURE(); }
+ } else {
+ ADD_FAILURE();
+ }
}
void endLayer() override {
int index = mIndex++;
@@ -1431,49 +1418,49 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) {
} else if (index == 11) {
EXPECT_EQ(200u, layer->viewportWidth);
EXPECT_EQ(200u, layer->viewportHeight);
- } else { ADD_FAILURE(); }
- }
- void endFrame(const Rect& repaintRect) override {
- EXPECT_EQ(12, mIndex++);
+ } else {
+ ADD_FAILURE();
+ }
}
+ void endFrame(const Rect& repaintRect) override { EXPECT_EQ(12, mIndex++); }
void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
EXPECT_EQ(13, mIndex++);
}
};
- auto child = TestUtils::createNode<RecordingCanvas>(50, 50, 150, 150,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- props.mutateLayerProperties().setType(LayerType::RenderLayer);
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
+ auto child = TestUtils::createNode<RecordingCanvas>(
+ 50, 50, 150, 150, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100);
*(child->getLayerHandle()) = &childLayer;
RenderNode* childPtr = child.get();
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [childPtr](RenderProperties& props, RecordingCanvas& canvas) {
- props.mutateLayerProperties().setType(LayerType::RenderLayer);
- SkPaint paint;
- paint.setColor(SK_ColorDKGRAY);
- canvas.drawRect(0, 0, 200, 200, paint);
-
- canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer);
- canvas.drawRenderNode(childPtr);
- canvas.restore();
- });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [childPtr](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(0, 0, 200, 200, paint);
+
+ canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer);
+ canvas.drawRenderNode(childPtr);
+ canvas.restore();
+ });
OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200);
*(parent->getLayerHandle()) = &parentLayer;
auto syncedNode = TestUtils::getSyncedNode(parent);
- LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100));
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferLayers(layerUpdateQueue);
frameBuilder.deferRenderNode(*syncedNode);
@@ -1486,7 +1473,6 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) {
*(parent->getLayerHandle()) = nullptr;
}
-
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, buildLayer) {
class BuildLayerTestRenderer : public TestRendererBase {
public:
@@ -1505,9 +1491,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, buildLayer) {
EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect())
<< "Damage rect should be used to clip layer content";
}
- void endLayer() override {
- EXPECT_EQ(2, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(2, mIndex++); }
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
ADD_FAILURE() << "Primary frame draw not expected in this test";
}
@@ -1516,11 +1500,11 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, buildLayer) {
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- props.mutateLayerProperties().setType(LayerType::RenderLayer);
- canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 10, 10, 110, 110, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
OffscreenBuffer** layerHandle = node->getLayerHandle();
// create RenderNode's layer here in same way prepareTree would
@@ -1530,7 +1514,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, buildLayer) {
TestUtils::syncHierarchyPropertiesAndDisplayList(node);
// only enqueue partial damage
- LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
// Draw, but pass empty node list, so no work is done for primary frame
@@ -1552,65 +1536,69 @@ static void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
canvas->drawRect(0, 0, 100, 100, paint);
}
static void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedRect(&canvas, expectedDrawOrder);
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedRect(&canvas, expectedDrawOrder);
+ });
node->mutateStagingProperties().setTranslationZ(z);
node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z);
- canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
+ canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
}
-static void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder,
+static void drawOrderedNode(
+ Canvas* canvas, uint8_t expectedDrawOrder,
std::function<void(RenderProperties& props, RecordingCanvas& canvas)> setup) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100,
[expectedDrawOrder, setup](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedRect(&canvas, expectedDrawOrder);
- if (setup) {
- setup(props, canvas);
- }
- });
- canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
+ drawOrderedRect(&canvas, expectedDrawOrder);
+ if (setup) {
+ setup(props, canvas);
+ }
+ });
+ canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
}
class ZReorderTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
- int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel
+ int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel
EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
}
};
-} // end anonymous namespace
+} // end anonymous namespace
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, zReorder) {
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.insertReorderBarrier(true);
- canvas.insertReorderBarrier(false);
- drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
- drawOrderedRect(&canvas, 1);
- canvas.insertReorderBarrier(true);
- drawOrderedNode(&canvas, 6, 2.0f);
- drawOrderedRect(&canvas, 3);
- drawOrderedNode(&canvas, 4, 0.0f);
- drawOrderedRect(&canvas, 5);
- drawOrderedNode(&canvas, 2, -2.0f);
- drawOrderedNode(&canvas, 7, 2.0f);
- canvas.insertReorderBarrier(false);
- drawOrderedRect(&canvas, 8);
- drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
- canvas.insertReorderBarrier(true); //reorder a node ahead of drawrect op
- drawOrderedRect(&canvas, 11);
- drawOrderedNode(&canvas, 10, -1.0f);
- canvas.insertReorderBarrier(false);
- canvas.insertReorderBarrier(true); //test with two empty reorder sections
- canvas.insertReorderBarrier(true);
- canvas.insertReorderBarrier(false);
- drawOrderedRect(&canvas, 12);
- });
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.insertReorderBarrier(true);
+ canvas.insertReorderBarrier(false);
+ drawOrderedNode(&canvas, 0,
+ 10.0f); // in reorder=false at this point, so played inorder
+ drawOrderedRect(&canvas, 1);
+ canvas.insertReorderBarrier(true);
+ drawOrderedNode(&canvas, 6, 2.0f);
+ drawOrderedRect(&canvas, 3);
+ drawOrderedNode(&canvas, 4, 0.0f);
+ drawOrderedRect(&canvas, 5);
+ drawOrderedNode(&canvas, 2, -2.0f);
+ drawOrderedNode(&canvas, 7, 2.0f);
+ canvas.insertReorderBarrier(false);
+ drawOrderedRect(&canvas, 8);
+ drawOrderedNode(&canvas, 9,
+ -10.0f); // in reorder=false at this point, so played inorder
+ canvas.insertReorderBarrier(true); // reorder a node ahead of drawrect op
+ drawOrderedRect(&canvas, 11);
+ drawOrderedNode(&canvas, 10, -1.0f);
+ canvas.insertReorderBarrier(false);
+ canvas.insertReorderBarrier(true); // test with two empty reorder sections
+ canvas.insertReorderBarrier(true);
+ canvas.insertReorderBarrier(false);
+ drawOrderedRect(&canvas, 12);
+ });
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
ZReorderTestRenderer renderer;
@@ -1628,28 +1616,28 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorder) {
Matrix4 expectedMatrix;
switch (index) {
- case 0:
- EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
- EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
- expectedMatrix.loadIdentity();
- EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
- break;
- case 1:
- EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds);
- EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
- expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0);
- ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
- EXPECT_EQ(Rect(-35, -30, 45, 50),
- Rect(state.computedState.localProjectionPathMask->getBounds()));
- break;
- case 2:
- EXPECT_EQ(Rect(100, 50), op.unmappedBounds);
- EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
- expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0);
- EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
- break;
- default:
- ADD_FAILURE();
+ case 0:
+ EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
+ EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
+ expectedMatrix.loadIdentity();
+ EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ break;
+ case 1:
+ EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds);
+ EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
+ expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0);
+ ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
+ EXPECT_EQ(Rect(-35, -30, 45, 50),
+ Rect(state.computedState.localProjectionPathMask->getBounds()));
+ break;
+ case 2:
+ EXPECT_EQ(Rect(100, 50), op.unmappedBounds);
+ EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
+ expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0);
+ EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ break;
+ default:
+ ADD_FAILURE();
}
EXPECT_EQ(expectedMatrix, state.computedState.transform);
}
@@ -1663,47 +1651,51 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorder) {
* The parent is scrolled by scrollX/scrollY, but this does not affect the background
* (which isn't affected by scroll).
*/
- auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.setProjectionReceiver(true);
- // scroll doesn't apply to background, so undone via translationX/Y
- // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
- properties.setTranslationX(scrollX);
- properties.setTranslationY(scrollY);
-
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
- auto projectingRipple = TestUtils::createNode<RecordingCanvas>(50, 0, 100, 50,
- [](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.setProjectBackwards(true);
- properties.setClipToBounds(false);
- SkPaint paint;
- paint.setColor(SK_ColorDKGRAY);
- canvas.drawRect(-10, -10, 60, 60, paint);
- });
- auto child = TestUtils::createNode<RecordingCanvas>(0, 50, 100, 100,
+ auto receiverBackground = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj
+ // receiver!
+ properties.setTranslationX(scrollX);
+ properties.setTranslationY(scrollY);
+
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
+ auto projectingRipple = TestUtils::createNode<RecordingCanvas>(
+ 50, 0, 100, 50, [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(-10, -10, 60, 60, paint);
+ });
+ auto child = TestUtils::createNode<RecordingCanvas>(
+ 0, 50, 100, 100,
[&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorBLUE);
- canvas.drawRect(0, 0, 100, 50, paint);
- canvas.drawRenderNode(projectingRipple.get());
- });
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+ SkPaint paint;
+ paint.setColor(SK_ColorBLUE);
+ canvas.drawRect(0, 0, 100, 50, paint);
+ canvas.drawRenderNode(projectingRipple.get());
+ });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100,
[&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
- // Set a rect outline for the projecting ripple to be masked against.
- properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
-
- canvas.save(SaveFlags::MatrixClip);
- canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
- canvas.drawRenderNode(receiverBackground.get());
- canvas.drawRenderNode(child.get());
- canvas.restore();
- });
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
+
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.translate(-scrollX,
+ -scrollY); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ canvas.restore();
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
ProjectionReorderTestRenderer renderer;
@@ -1723,9 +1715,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionHwLayer) {
EXPECT_EQ(1, mIndex++);
ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
}
- void endLayer() override {
- EXPECT_EQ(2, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(2, mIndex++); }
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(3, mIndex++);
ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
@@ -1737,60 +1727,64 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionHwLayer) {
expected.loadTranslate(100 - scrollX, 100 - scrollY, 0);
EXPECT_EQ(expected, state.computedState.transform);
EXPECT_EQ(Rect(-85, -80, 295, 300),
- Rect(state.computedState.localProjectionPathMask->getBounds()));
+ Rect(state.computedState.localProjectionPathMask->getBounds()));
}
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(5, mIndex++);
ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
}
};
- auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
- [](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.setProjectionReceiver(true);
- // scroll doesn't apply to background, so undone via translationX/Y
- // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
- properties.setTranslationX(scrollX);
- properties.setTranslationY(scrollY);
+ auto receiverBackground = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 400, [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj
+ // receiver!
+ properties.setTranslationX(scrollX);
+ properties.setTranslationY(scrollY);
- canvas.drawRect(0, 0, 400, 400, SkPaint());
- });
- auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.setProjectBackwards(true);
- properties.setClipToBounds(false);
- canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
- });
- auto child = TestUtils::createNode<RecordingCanvas>(100, 100, 300, 300,
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+ });
+ auto projectingRipple = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
+ });
+ auto child = TestUtils::createNode<RecordingCanvas>(
+ 100, 100, 300, 300,
[&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.mutateLayerProperties().setType(LayerType::RenderLayer);
- canvas.drawRenderNode(projectingRipple.get());
- canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint());
- });
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
+ properties.mutateLayerProperties().setType(LayerType::RenderLayer);
+ canvas.drawRenderNode(projectingRipple.get());
+ canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint());
+ });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 400,
[&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
- // Set a rect outline for the projecting ripple to be masked against.
- properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
- canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
- canvas.drawRenderNode(receiverBackground.get());
- canvas.drawRenderNode(child.get());
- });
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
+ canvas.translate(-scrollX,
+ -scrollY); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ });
OffscreenBuffer** layerHandle = child->getLayerHandle();
// create RenderNode's layer here in same way prepareTree would, setting windowTransform
OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200);
Matrix4 windowTransform;
- windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin
+ windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin
layer.setWindowTransform(windowTransform);
*layerHandle = &layer;
auto syncedNode = TestUtils::getSyncedNode(parent);
- LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200));
- FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferLayers(layerUpdateQueue);
frameBuilder.deferRenderNode(*syncedNode);
@@ -1819,37 +1813,41 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionChildScroll) {
EXPECT_TRUE(state.computedState.transform.isIdentity());
}
};
- auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
- [](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.setProjectionReceiver(true);
- canvas.drawRect(0, 0, 400, 400, SkPaint());
- });
- auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& properties, RecordingCanvas& canvas) {
- // scroll doesn't apply to background, so undone via translationX/Y
- // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
- properties.setTranslationX(scrollX);
- properties.setTranslationY(scrollY);
- properties.setProjectBackwards(true);
- properties.setClipToBounds(false);
- canvas.drawOval(0, 0, 200, 200, SkPaint());
- });
- auto child = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
+ auto receiverBackground = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 400, [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+ });
+ auto projectingRipple = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& properties, RecordingCanvas& canvas) {
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj
+ // receiver!
+ properties.setTranslationX(scrollX);
+ properties.setTranslationY(scrollY);
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(0, 0, 200, 200, SkPaint());
+ });
+ auto child = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 400,
[&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
- // Record time clip will be ignored by projectee
- canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
-
- canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
- canvas.drawRenderNode(projectingRipple.get());
- });
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
+ // Record time clip will be ignored by projectee
+ canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
+
+ canvas.translate(-scrollX,
+ -scrollY); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(projectingRipple.get());
+ });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 400, 400,
[&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
- canvas.drawRenderNode(receiverBackground.get());
- canvas.drawRenderNode(child.get());
- });
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
ProjectionChildScrollTestRenderer renderer;
@@ -1859,14 +1857,14 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionChildScroll) {
// creates a 100x100 shadow casting node with provided translationZ
static sp<RenderNode> createWhiteRectShadowCaster(float translationZ) {
- return TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [translationZ](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.setTranslationZ(translationZ);
- properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f);
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
+ return TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [translationZ](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setTranslationZ(translationZ);
+ properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f);
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadow) {
@@ -1887,14 +1885,14 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadow) {
}
};
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.insertReorderBarrier(true);
- canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
- });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.insertReorderBarrier(true);
+ canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
ShadowTestRenderer renderer;
@@ -1917,9 +1915,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowSaveLayer) {
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(2, mIndex++);
}
- void endLayer() override {
- EXPECT_EQ(3, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(3, mIndex++); }
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(4, mIndex++);
}
@@ -1928,19 +1924,20 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowSaveLayer) {
}
};
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- // save/restore outside of reorderBarrier, so they don't get moved out of place
- canvas.translate(20, 10);
- int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer);
- canvas.insertReorderBarrier(true);
- canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
- canvas.insertReorderBarrier(false);
- canvas.restoreToCount(count);
- });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ // save/restore outside of reorderBarrier, so they don't get moved out of place
+ canvas.translate(20, 10);
+ int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer);
+ canvas.insertReorderBarrier(true);
+ canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
+ canvas.insertReorderBarrier(false);
+ canvas.restoreToCount(count);
+ });
FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
+ (FrameBuilder::LightGeometry){{100, 100, 100}, 50},
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
ShadowSaveLayerTestRenderer renderer;
@@ -1963,38 +1960,37 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowHwLayer) {
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(2, mIndex++);
}
- void endLayer() override {
- EXPECT_EQ(3, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(3, mIndex++); }
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(4, mIndex++);
}
};
- auto parent = TestUtils::createNode<RecordingCanvas>(50, 60, 150, 160,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- props.mutateLayerProperties().setType(LayerType::RenderLayer);
- canvas.insertReorderBarrier(true);
- canvas.save(SaveFlags::MatrixClip);
- canvas.translate(20, 10);
- canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
- canvas.restore();
- });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 50, 60, 150, 160, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
+ canvas.insertReorderBarrier(true);
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.translate(20, 10);
+ canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
+ canvas.restore();
+ });
OffscreenBuffer** layerHandle = parent->getLayerHandle();
// create RenderNode's layer here in same way prepareTree would, setting windowTransform
OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
Matrix4 windowTransform;
- windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin
+ windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin
layer.setWindowTransform(windowTransform);
*layerHandle = &layer;
auto syncedNode = TestUtils::getSyncedNode(parent);
- LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance());
+ (FrameBuilder::LightGeometry){{100, 100, 100}, 30},
+ Caches::getInstance());
frameBuilder.deferLayers(layerUpdateQueue);
frameBuilder.deferRenderNode(*syncedNode);
@@ -2018,14 +2014,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowLayering) {
EXPECT_TRUE(index == 2 || index == 3);
}
};
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.insertReorderBarrier(true);
- canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
- canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get());
- });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.insertReorderBarrier(true);
+ canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
+ canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get());
+ });
FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
+ (FrameBuilder::LightGeometry){{100, 100, 100}, 50},
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
ShadowLayeringTestRenderer renderer;
@@ -2045,17 +2042,18 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowClipping) {
EXPECT_EQ(1, mIndex++);
}
};
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- // Apply a clip before the reorder barrier/shadow casting child is drawn.
- // This clip must be applied to the shadow cast by the child.
- canvas.clipRect(25, 25, 75, 75, SkClipOp::kIntersect);
- canvas.insertReorderBarrier(true);
- canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
- });
+ auto parent = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ // Apply a clip before the reorder barrier/shadow casting child is drawn.
+ // This clip must be applied to the shadow cast by the child.
+ canvas.clipRect(25, 25, 75, 75, SkClipOp::kIntersect);
+ canvas.insertReorderBarrier(true);
+ canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
+ });
FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
+ (FrameBuilder::LightGeometry){{100, 100, 100}, 50},
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
ShadowClippingTestRenderer renderer;
@@ -2063,11 +2061,13 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowClipping) {
EXPECT_EQ(2, renderer.getIndex());
}
-static void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
+static void testProperty(
+ std::function<void(RenderProperties&)> propSetupCallback,
std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) {
class PropertyTestRenderer : public TestRendererBase {
public:
- explicit PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback)
+ explicit PropertyTestRenderer(
+ std::function<void(const RectOp&, const BakedOpState&)> callback)
: mCallback(callback) {}
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(mIndex++, 0);
@@ -2076,16 +2076,16 @@ static void testProperty(std::function<void(RenderProperties&)> propSetupCallbac
std::function<void(const RectOp&, const BakedOpState&)> mCallback;
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) {
- propSetupCallback(props);
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) {
+ propSetupCallback(props);
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
PropertyTestRenderer renderer(opValidateCallback);
@@ -2094,78 +2094,89 @@ static void testProperty(std::function<void(RenderProperties&)> propSetupCallbac
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) {
- testProperty([](RenderProperties& properties) {
- properties.setAlpha(0.5f);
- properties.setHasOverlappingRendering(false);
- }, [](const RectOp& op, const BakedOpState& state) {
- EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op";
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.setAlpha(0.5f);
+ properties.setHasOverlappingRendering(false);
+ },
+ [](const RectOp& op, const BakedOpState& state) {
+ EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op";
+ });
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropClipping) {
- testProperty([](RenderProperties& properties) {
- properties.setClipToBounds(true);
- properties.setClipBounds(Rect(10, 20, 300, 400));
- }, [](const RectOp& op, const BakedOpState& state) {
- EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds)
- << "Clip rect should be intersection of node bounds and clip bounds";
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.setClipToBounds(true);
+ properties.setClipBounds(Rect(10, 20, 300, 400));
+ },
+ [](const RectOp& op, const BakedOpState& state) {
+ EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds)
+ << "Clip rect should be intersection of node bounds and clip bounds";
+ });
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropRevealClip) {
- testProperty([](RenderProperties& properties) {
- properties.mutableRevealClip().set(true, 50, 50, 25);
- }, [](const RectOp& op, const BakedOpState& state) {
- ASSERT_NE(nullptr, state.roundRectClipState);
- EXPECT_TRUE(state.roundRectClipState->highPriority);
- EXPECT_EQ(25, state.roundRectClipState->radius);
- EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect);
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.mutableRevealClip().set(true, 50, 50, 25);
+ },
+ [](const RectOp& op, const BakedOpState& state) {
+ ASSERT_NE(nullptr, state.roundRectClipState);
+ EXPECT_TRUE(state.roundRectClipState->highPriority);
+ EXPECT_EQ(25, state.roundRectClipState->radius);
+ EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect);
+ });
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOutlineClip) {
- testProperty([](RenderProperties& properties) {
- properties.mutableOutline().setShouldClip(true);
- properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
- }, [](const RectOp& op, const BakedOpState& state) {
- ASSERT_NE(nullptr, state.roundRectClipState);
- EXPECT_FALSE(state.roundRectClipState->highPriority);
- EXPECT_EQ(5, state.roundRectClipState->radius);
- EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect);
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.mutableOutline().setShouldClip(true);
+ properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
+ },
+ [](const RectOp& op, const BakedOpState& state) {
+ ASSERT_NE(nullptr, state.roundRectClipState);
+ EXPECT_FALSE(state.roundRectClipState->highPriority);
+ EXPECT_EQ(5, state.roundRectClipState->radius);
+ EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect);
+ });
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropTransform) {
- testProperty([](RenderProperties& properties) {
- properties.setLeftTopRightBottom(10, 10, 110, 110);
-
- SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
- properties.setStaticMatrix(&staticMatrix);
-
- // ignored, since static overrides animation
- SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
- properties.setAnimationMatrix(&animationMatrix);
-
- properties.setTranslationX(10);
- properties.setTranslationY(20);
- properties.setScaleX(0.5f);
- properties.setScaleY(0.7f);
- }, [](const RectOp& op, const BakedOpState& state) {
- Matrix4 matrix;
- matrix.loadTranslate(10, 10, 0); // left, top
- matrix.scale(1.2f, 1.2f, 1); // static matrix
- // ignore animation matrix, since static overrides it
-
- // translation xy
- matrix.translate(10, 20);
-
- // scale xy (from default pivot - center)
- matrix.translate(50, 50);
- matrix.scale(0.5f, 0.7f, 1);
- matrix.translate(-50, -50);
- EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform)
- << "Op draw matrix must match expected combination of transformation properties";
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.setLeftTopRightBottom(10, 10, 110, 110);
+
+ SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
+ properties.setStaticMatrix(&staticMatrix);
+
+ // ignored, since static overrides animation
+ SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
+ properties.setAnimationMatrix(&animationMatrix);
+
+ properties.setTranslationX(10);
+ properties.setTranslationY(20);
+ properties.setScaleX(0.5f);
+ properties.setScaleY(0.7f);
+ },
+ [](const RectOp& op, const BakedOpState& state) {
+ Matrix4 matrix;
+ matrix.loadTranslate(10, 10, 0); // left, top
+ matrix.scale(1.2f, 1.2f, 1); // static matrix
+ // ignore animation matrix, since static overrides it
+
+ // translation xy
+ matrix.translate(10, 20);
+
+ // scale xy (from default pivot - center)
+ matrix.translate(50, 50);
+ matrix.scale(0.5f, 0.7f, 1);
+ matrix.translate(-50, -50);
+ EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform)
+ << "Op draw matrix must match expected combination of transformation "
+ "properties";
+ });
}
struct SaveLayerAlphaData {
@@ -2186,11 +2197,10 @@ struct SaveLayerAlphaData {
* (for efficiency, and to fit in layer size constraints) based on parent clip.
*/
void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
- std::function<void(RenderProperties&)> propSetupCallback) {
+ std::function<void(RenderProperties&)> propSetupCallback) {
class SaveLayerAlphaClipTestRenderer : public TestRendererBase {
public:
- explicit SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData)
- : mOutData(outData) {}
+ explicit SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) : mOutData(outData) {}
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
EXPECT_EQ(0, mIndex++);
@@ -2204,9 +2214,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
mOutData->rectClippedBounds = state.computedState.clippedBounds;
mOutData->rectMatrix = state.computedState.transform;
}
- void endLayer() override {
- EXPECT_EQ(2, mIndex++);
- }
+ void endLayer() override { EXPECT_EQ(2, mIndex++); }
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(3, mIndex++);
mOutData->drawLayerMatrix = state.computedState.transform;
@@ -2214,27 +2222,29 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
EXPECT_EQ(4, mIndex++);
}
+
private:
SaveLayerAlphaData* mOutData;
};
ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize())
<< "Node must be bigger than max texture size to exercise saveLayer codepath";
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 10000, 10000,
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 10000, 10000,
[&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) {
- properties.setHasOverlappingRendering(true);
- properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer
- // apply other properties
- propSetupCallback(properties);
-
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 10000, 10000, paint);
- });
- auto syncedNode = TestUtils::getSyncedNode(node); // sync before querying height
-
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometry, Caches::getInstance());
+ properties.setHasOverlappingRendering(true);
+ properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer
+ // apply other properties
+ propSetupCallback(properties);
+
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 10000, 10000, paint);
+ });
+ auto syncedNode = TestUtils::getSyncedNode(node); // sync before querying height
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*syncedNode);
SaveLayerAlphaClipTestRenderer renderer(outObservedData);
@@ -2247,8 +2257,8 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
SaveLayerAlphaData observedData;
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
- properties.setTranslationX(10); // offset rendering content
- properties.setTranslationY(-2000); // offset rendering content
+ properties.setTranslationX(10); // offset rendering content
+ properties.setTranslationY(-2000); // offset rendering content
});
EXPECT_EQ(190u, observedData.layerWidth);
EXPECT_EQ(200u, observedData.layerHeight);
@@ -2260,7 +2270,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig)
<< "expect content to be translated as part of being clipped";
expected.loadTranslate(10, 0, 0);
EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix)
- << "expect drawLayer to be translated as part of being clipped";
+ << "expect drawLayer to be translated as part of being clipped";
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
@@ -2306,14 +2316,14 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clip_replace) {
<< "Expect resolved clip to be intersection of viewport clip and clip op";
}
};
- auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
- canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
- });
-
- FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50,
- sLightGeometry, Caches::getInstance());
+ auto node = TestUtils::createNode<RecordingCanvas>(
+ 20, 20, 30, 30, [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
ClipReplaceTestRenderer renderer;
@@ -2329,21 +2339,22 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMidd
|
R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setProjectionReceiver(true);
+ }); // nodeB
+ drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2360,22 +2371,24 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
|
R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 2
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 3
- props.setProjectionReceiver(true);
- } ); //nodeE
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
+ drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 3, [](RenderProperties& props,
+ RecordingCanvas& canvas) { // drawn as 2
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ drawOrderedNode(&canvas, 2, [](RenderProperties& props,
+ RecordingCanvas& canvas) { // drawn as 3
+ props.setProjectionReceiver(true);
+ }); // nodeE
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2391,20 +2404,21 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
|
R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) {
- //not having a projection receiver is an undefined behavior
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
+ drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 255,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ // not having a projection receiver is an undefined behavior
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2420,20 +2434,21 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivabl
|
R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectionReceiver(true);
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
+ drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setProjectionReceiver(true);
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2442,21 +2457,23 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivabl
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) {
- //having a node that is projected on itself is an undefined/unexpected behavior
- props.setProjectionReceiver(true);
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
+ drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 255,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ // having a node that is projected on itself is an
+ // undefined/unexpected behavior
+ props.setProjectionReceiver(true);
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2465,9 +2482,9 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceiva
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
- //TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a
- //bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical
- //tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling
+ // TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a
+ // bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical
+ // tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling
/* R is backward projected on B. R is not expected to be drawn (see Sibling2 outcome below),
but for some reason it is drawn.
A
@@ -2475,21 +2492,21 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSiblin
/ | \
B C R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
- } ); //nodeC
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- }); //nodeA
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setProjectionReceiver(true);
+ }); // nodeB
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, RecordingCanvas& canvas) {}); // nodeC
+ drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeA
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2506,23 +2523,27 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSiblin
/ | \
B C R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //G
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //B
- props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
- } ); //nodeC
- drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { //R
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeG
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, [](RenderProperties& props,
+ RecordingCanvas& canvas) { // G
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // B
+ props.setProjectionReceiver(true);
+ }); // nodeB
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // C
+ }); // nodeC
+ drawOrderedNode(&canvas, 255,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // R
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeG
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2540,21 +2561,23 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentRece
|
R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectionReceiver(true);
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- } ); //nodeB
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.setProjectionReceiver(true);
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 2, [](RenderProperties& props,
+ RecordingCanvas& canvas) {
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeB
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2570,24 +2593,28 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables)
/ \
G R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
- props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //G
- props.setProjectionReceiver(true);
- } ); //nodeG
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //R
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // B
+ props.setProjectionReceiver(true);
+ }); // nodeB
+ drawOrderedNode(&canvas, 2, [](RenderProperties& props,
+ RecordingCanvas& canvas) { // C
+ drawOrderedNode(&canvas, 3,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // G
+ props.setProjectionReceiver(true);
+ }); // nodeG
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // R
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2603,24 +2630,28 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesL
/ \
G R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
- props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //G
- props.setProjectionReceiver(true);
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeG
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // B
+ props.setProjectionReceiver(true);
+ }); // nodeB
+ drawOrderedNode(&canvas, 2, [](RenderProperties& props,
+ RecordingCanvas& canvas) { // C
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // G
+ props.setProjectionReceiver(true);
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeG
+ drawOrderedNode(&canvas, 3,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // R
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2638,26 +2669,31 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesD
|
R
*/
- auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RenderProperties& props, RecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
- props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //C
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //G
- props.setProjectionReceiver(true);
- } ); //nodeG
- drawOrderedNode(&canvas, 4, [](RenderProperties& props, RecordingCanvas& canvas) { //D
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeD
- } ); //nodeC
- }); //nodeA
-
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometry, Caches::getInstance());
+ auto nodeA = TestUtils::createNode<RecordingCanvas>(
+ 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // B
+ props.setProjectionReceiver(true);
+ }); // nodeB
+ drawOrderedNode(&canvas, 1, [](RenderProperties& props,
+ RecordingCanvas& canvas) { // C
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, RecordingCanvas& canvas) { // G
+ props.setProjectionReceiver(true);
+ }); // nodeG
+ drawOrderedNode(
+ &canvas, 4, [](RenderProperties& props, RecordingCanvas& canvas) { // D
+ drawOrderedNode(&canvas, 3, [](RenderProperties& props,
+ RecordingCanvas& canvas) { // R
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeD
+ }); // nodeC
+ }); // nodeA
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
ZReorderTestRenderer renderer;
@@ -2665,5 +2701,5 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesD
EXPECT_EQ(5, renderer.getIndex());
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/unit/GlopBuilderTests.cpp b/libs/hwui/tests/unit/GlopBuilderTests.cpp
index caeb6bf0081b..c8bfc99fac92 100644
--- a/libs/hwui/tests/unit/GlopBuilderTests.cpp
+++ b/libs/hwui/tests/unit/GlopBuilderTests.cpp
@@ -28,8 +28,7 @@ using namespace android::uirenderer;
static void expectFillEq(Glop::Fill& expectedFill, Glop::Fill& builtFill) {
EXPECT_EQ(expectedFill.colorEnabled, builtFill.colorEnabled);
- if (expectedFill.colorEnabled)
- EXPECT_EQ(expectedFill.color, builtFill.color);
+ if (expectedFill.colorEnabled) EXPECT_EQ(expectedFill.color, builtFill.color);
EXPECT_EQ(expectedFill.filterMode, builtFill.filterMode);
if (expectedFill.filterMode == ProgramDescription::ColorFilterMode::Blend) {
@@ -38,15 +37,15 @@ static void expectFillEq(Glop::Fill& expectedFill, Glop::Fill& builtFill) {
Glop::Fill::Filter::Matrix& expectedMatrix = expectedFill.filter.matrix;
Glop::Fill::Filter::Matrix& builtMatrix = expectedFill.filter.matrix;
EXPECT_TRUE(std::memcmp(expectedMatrix.matrix, builtMatrix.matrix,
- sizeof(Glop::Fill::Filter::Matrix::matrix)));
+ sizeof(Glop::Fill::Filter::Matrix::matrix)));
EXPECT_TRUE(std::memcmp(expectedMatrix.vector, builtMatrix.vector,
- sizeof(Glop::Fill::Filter::Matrix::vector)));
+ sizeof(Glop::Fill::Filter::Matrix::vector)));
}
EXPECT_EQ(expectedFill.skiaShaderData.skiaShaderType, builtFill.skiaShaderData.skiaShaderType);
EXPECT_EQ(expectedFill.texture.clamp, builtFill.texture.clamp);
EXPECT_EQ(expectedFill.texture.filter, builtFill.texture.filter);
- EXPECT_TRUE((expectedFill.texture.texture && builtFill.texture.texture)
- || (!expectedFill.texture.texture && !builtFill.texture.texture));
+ EXPECT_TRUE((expectedFill.texture.texture && builtFill.texture.texture) ||
+ (!expectedFill.texture.texture && !builtFill.texture.texture));
if (expectedFill.texture.texture) {
EXPECT_EQ(expectedFill.texture.texture->target(), builtFill.texture.texture->target());
}
@@ -97,22 +96,23 @@ static void expectGlopEq(Glop& expectedGlop, Glop& builtGlop) {
static std::unique_ptr<Glop> blackUnitQuadGlop(RenderState& renderState) {
std::unique_ptr<Glop> glop(new Glop());
- glop->blend = { GL_ZERO, GL_ZERO };
+ glop->blend = {GL_ZERO, GL_ZERO};
glop->mesh.elementCount = 4;
glop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
glop->mesh.indices.indices = nullptr;
glop->mesh.indices.bufferObject = GL_ZERO;
- glop->mesh.vertices = {
- renderState.meshState().getUnitQuadVBO(),
- VertexAttribFlags::None,
- nullptr, nullptr, nullptr,
- kTextureVertexStride };
+ glop->mesh.vertices = {renderState.meshState().getUnitQuadVBO(),
+ VertexAttribFlags::None,
+ nullptr,
+ nullptr,
+ nullptr,
+ kTextureVertexStride};
glop->transform.modelView.loadIdentity();
glop->fill.colorEnabled = true;
glop->fill.color.set(Color::Black);
glop->fill.skiaShaderData.skiaShaderType = kNone_SkiaShaderType;
glop->fill.filterMode = ProgramDescription::ColorFilterMode::None;
- glop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
+ glop->fill.texture = {nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr};
return glop;
}
diff --git a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
index 8cbd24edbde2..9bfb08292be2 100644
--- a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
+++ b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-
-#include <gtest/gtest.h>
#include <GpuMemoryTracker.h>
+#include <gtest/gtest.h>
#include "renderthread/EglManager.h"
#include "renderthread/RenderThread.h"
@@ -32,9 +31,7 @@ class TestGPUObject : public GpuMemoryTracker {
public:
TestGPUObject() : GpuMemoryTracker(GpuObjectType::Texture) {}
- void changeSize(int newSize) {
- notifySizeChanged(newSize);
- }
+ void changeSize(int newSize) { notifySizeChanged(newSize); }
};
// Other tests may have created a renderthread and EGL context.
@@ -42,9 +39,7 @@ public:
// current thread can spoof being a GPU thread
static void destroyEglContext() {
if (TestUtils::isRenderThreadRunning()) {
- TestUtils::runOnRenderThread([](RenderThread& thread) {
- thread.eglManager().destroy();
- });
+ TestUtils::runOnRenderThread([](RenderThread& thread) { thread.eglManager().destroy(); });
}
}
diff --git a/libs/hwui/tests/unit/GradientCacheTests.cpp b/libs/hwui/tests/unit/GradientCacheTests.cpp
index a3b346f11a87..6710c71c386f 100644
--- a/libs/hwui/tests/unit/GradientCacheTests.cpp
+++ b/libs/hwui/tests/unit/GradientCacheTests.cpp
@@ -28,12 +28,12 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(GradientCache, addRemove) {
GradientCache cache(extensions);
ASSERT_LT(1000u, cache.getMaxSize()) << "Expect non-trivial size";
- SkColor colors[] = { 0xFF00FF00, 0xFFFF0000, 0xFF0000FF };
- float positions[] = { 1, 2, 3 };
+ SkColor colors[] = {0xFF00FF00, 0xFFFF0000, 0xFF0000FF};
+ float positions[] = {1, 2, 3};
Texture* texture = cache.get(colors, positions, 3);
ASSERT_TRUE(texture);
ASSERT_FALSE(texture->cleanup);
- ASSERT_EQ((uint32_t) texture->objectSize(), cache.getSize());
+ ASSERT_EQ((uint32_t)texture->objectSize(), cache.getSize());
ASSERT_TRUE(cache.getSize());
cache.clear();
ASSERT_EQ(cache.getSize(), 0u);
diff --git a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
index fda3a79a69da..098b4ccea8cf 100644
--- a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
+++ b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
@@ -16,14 +16,13 @@
#include <gtest/gtest.h>
+#include "protos/graphicsstats.pb.h"
#include "service/GraphicsStatsService.h"
-#include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
using namespace android;
@@ -35,8 +34,8 @@ std::string findRootPath() {
// < 1023 because we need room for the null terminator
if (r <= 0 || r > 1023) {
int err = errno;
- fprintf(stderr, "Failed to read from /proc/self/exe; r=%zd, err=%d (%s)\n",
- r, err, strerror(err));
+ fprintf(stderr, "Failed to read from /proc/self/exe; r=%zd, err=%d (%s)\n", r, err,
+ strerror(err));
exit(EXIT_FAILURE);
}
while (--r > 0) {
@@ -74,7 +73,7 @@ TEST(GraphicsStats, saveLoad) {
mockData.editSlowFrameCounts()[i] = (i % 5) + 1;
}
GraphicsStatsService::saveBuffer(path, packageName, 5, 3000, 7000, &mockData);
- service::GraphicsStatsProto loadedProto;
+ protos::GraphicsStatsProto loadedProto;
EXPECT_TRUE(GraphicsStatsService::parseFromFile(path, &loadedProto));
// Clean up the file
unlink(path.c_str());
@@ -88,8 +87,8 @@ TEST(GraphicsStats, saveLoad) {
EXPECT_EQ(20, loadedProto.summary().janky_frames());
EXPECT_EQ(100, loadedProto.summary().total_frames());
EXPECT_EQ(mockData.editFrameCounts().size() + mockData.editSlowFrameCounts().size(),
- (size_t) loadedProto.histogram_size());
- for (size_t i = 0; i < (size_t) loadedProto.histogram_size(); i++) {
+ (size_t)loadedProto.histogram_size());
+ for (size_t i = 0; i < (size_t)loadedProto.histogram_size(); i++) {
int expectedCount, expectedBucket;
if (i < mockData.editFrameCounts().size()) {
expectedCount = ((i % 10) + 1) * 2;
@@ -130,7 +129,7 @@ TEST(GraphicsStats, merge) {
}
GraphicsStatsService::saveBuffer(path, packageName, 5, 7050, 10000, &mockData);
- service::GraphicsStatsProto loadedProto;
+ protos::GraphicsStatsProto loadedProto;
EXPECT_TRUE(GraphicsStatsService::parseFromFile(path, &loadedProto));
// Clean up the file
unlink(path.c_str());
@@ -144,8 +143,8 @@ TEST(GraphicsStats, merge) {
EXPECT_EQ(20 + 50, loadedProto.summary().janky_frames());
EXPECT_EQ(100 + 500, loadedProto.summary().total_frames());
EXPECT_EQ(mockData.editFrameCounts().size() + mockData.editSlowFrameCounts().size(),
- (size_t) loadedProto.histogram_size());
- for (size_t i = 0; i < (size_t) loadedProto.histogram_size(); i++) {
+ (size_t)loadedProto.histogram_size());
+ for (size_t i = 0; i < (size_t)loadedProto.histogram_size(); i++) {
int expectedCount, expectedBucket;
if (i < mockData.editFrameCounts().size()) {
expectedCount = ((i % 10) + 1) * 2;
diff --git a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
index 91c7514e271e..217d63f9c2e1 100644
--- a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
+++ b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
@@ -51,9 +51,9 @@ TEST(LayerUpdateQueue, enqueueSimple) {
EXPECT_EQ(a.get(), queue.entries()[0].renderNode.get());
EXPECT_EQ(Rect(25, 25, 75, 75), queue.entries()[0].damage);
EXPECT_EQ(b.get(), queue.entries()[1].renderNode.get());
- EXPECT_EQ(Rect(100, 100, 200, 200), queue.entries()[1].damage); // clipped to bounds
+ EXPECT_EQ(Rect(100, 100, 200, 200), queue.entries()[1].damage); // clipped to bounds
EXPECT_EQ(c.get(), queue.entries()[2].renderNode.get());
- EXPECT_EQ(Rect(0, 0, 1, 1), queue.entries()[2].damage); // rounded out
+ EXPECT_EQ(Rect(0, 0, 1, 1), queue.entries()[2].damage); // rounded out
}
TEST(LayerUpdateQueue, enqueueUnion) {
@@ -81,6 +81,5 @@ TEST(LayerUpdateQueue, clear) {
EXPECT_TRUE(queue.entries().empty());
}
-
};
};
diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp
index 19d7ef59e397..20ec0848212f 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "BakedOpRenderer.h"
#include "BakedOpDispatcher.h"
+#include "BakedOpRenderer.h"
#include "FrameBuilder.h"
#include "LayerUpdateQueue.h"
#include "RecordingCanvas.h"
@@ -26,12 +26,11 @@
using namespace android;
using namespace android::uirenderer;
-const FrameBuilder::LightGeometry sLightGeometery = { {100, 100, 100}, 50};
-const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
+const FrameBuilder::LightGeometry sLightGeometery = {{100, 100, 100}, 50};
+const BakedOpRenderer::LightInfo sLightInfo = {128, 128};
RENDERTHREAD_OPENGL_PIPELINE_TEST(LeakCheck, saveLayer_overdrawRejection) {
- auto node = TestUtils::createNode(0, 0, 100, 100,
- [](RenderProperties& props, Canvas& canvas) {
+ auto node = TestUtils::createNode(0, 0, 100, 100, [](RenderProperties& props, Canvas& canvas) {
canvas.saveLayerAlpha(0, 0, 100, 100, 128, SaveFlags::ClipToLayer);
canvas.drawRect(0, 0, 100, 100, SkPaint());
canvas.restore();
@@ -42,16 +41,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(LeakCheck, saveLayer_overdrawRejection) {
RenderState& renderState = renderThread.renderState();
Caches& caches = Caches::getInstance();
- FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
- sLightGeometery, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometery,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(LeakCheck, saveLayerUnclipped_simple) {
- auto node = TestUtils::createNode(0, 0, 200, 200,
- [](RenderProperties& props, Canvas& canvas) {
+ auto node = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
canvas.drawRect(0, 0, 200, 200, SkPaint());
canvas.restore();
@@ -59,8 +57,8 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(LeakCheck, saveLayerUnclipped_simple) {
RenderState& renderState = renderThread.renderState();
Caches& caches = Caches::getInstance();
- FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
- sLightGeometery, Caches::getInstance());
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, sLightGeometery,
+ Caches::getInstance());
frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
diff --git a/libs/hwui/tests/unit/LinearAllocatorTests.cpp b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
index ffcbf128fc3a..1038da3c4cd0 100644
--- a/libs/hwui/tests/unit/LinearAllocatorTests.cpp
+++ b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
@@ -43,7 +43,7 @@ TEST(LinearAllocator, create) {
}
TEST(LinearAllocator, dtor) {
- int destroyed[10] = { 0 };
+ int destroyed[10] = {0};
{
LinearAllocator la;
for (int i = 0; i < 5; i++) {
@@ -111,7 +111,6 @@ TEST(LinearStdAllocator, simpleAllocate) {
EXPECT_LT(lastLocation, &v[0]);
EXPECT_GT(lastLocation + 20, &v[0]);
-
}
TEST(LsaVector, dtorCheck) {
@@ -126,7 +125,7 @@ TEST(LsaVector, dtorCheck) {
vector.emplace_back(new TestUtils::SignalingDtor(&destroyed));
}
EXPECT_EQ(0, destroyed);
- EXPECT_EQ(size, (int) vector.size());
+ EXPECT_EQ(size, (int)vector.size());
}
EXPECT_EQ(size, destroyed);
}
diff --git a/libs/hwui/tests/unit/MatrixTests.cpp b/libs/hwui/tests/unit/MatrixTests.cpp
index eddab878a49d..16a396e00790 100644
--- a/libs/hwui/tests/unit/MatrixTests.cpp
+++ b/libs/hwui/tests/unit/MatrixTests.cpp
@@ -32,8 +32,7 @@ TEST(Matrix, mapRect_emptyScaleSkew) {
ASSERT_TRUE(empty.isEmpty());
scaleMatrix.mapRect(empty);
EXPECT_EQ(Rect(170, 215, 250, 1015), empty);
- EXPECT_FALSE(empty.isEmpty())
- << "Empty 'line' rect doesn't remain empty when skewed.";
+ EXPECT_FALSE(empty.isEmpty()) << "Empty 'line' rect doesn't remain empty when skewed.";
}
TEST(Matrix, mapRect_emptyRotate) {
@@ -45,6 +44,5 @@ TEST(Matrix, mapRect_emptyRotate) {
Rect lineRect(0, 100);
ASSERT_TRUE(lineRect.isEmpty());
skewMatrix.mapRect(lineRect);
- EXPECT_FALSE(lineRect.isEmpty())
- << "Empty 'line' rect doesn't remain empty when rotated.";
+ EXPECT_FALSE(lineRect.isEmpty()) << "Empty 'line' rect doesn't remain empty when rotated.";
}
diff --git a/libs/hwui/tests/unit/MeshStateTests.cpp b/libs/hwui/tests/unit/MeshStateTests.cpp
index 511d6d25fbaf..1573fd30d5cb 100644
--- a/libs/hwui/tests/unit/MeshStateTests.cpp
+++ b/libs/hwui/tests/unit/MeshStateTests.cpp
@@ -16,8 +16,8 @@
#include <debug/MockGlesDriver.h>
#include <debug/ScopedReplaceDriver.h>
-#include <gtest/gtest.h>
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <renderstate/MeshState.h>
#include <tests/common/TestUtils.h>
@@ -32,5 +32,6 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(MeshState, genOrUpdate) {
EXPECT_CALL(mockGlDriver, glBufferData_(_, _, _, _));
GLuint buffer = 0;
- renderThread.renderState().meshState().genOrUpdateMeshBuffer(&buffer, 10, nullptr, GL_DYNAMIC_DRAW);
+ renderThread.renderState().meshState().genOrUpdateMeshBuffer(&buffer, 10, nullptr,
+ GL_DYNAMIC_DRAW);
}
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 308fef303740..0d4736757629 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
#include <Rect.h>
+#include <gtest/gtest.h>
#include <renderstate/OffscreenBufferPool.h>
#include <tests/common/TestUtils.h>
@@ -56,12 +56,10 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(OffscreenBuffer, constructWideColorGamut) {
RENDERTHREAD_OPENGL_PIPELINE_TEST(OffscreenBuffer, getTextureCoordinates) {
OffscreenBuffer layerAligned(renderThread.renderState(), Caches::getInstance(), 256u, 256u);
- EXPECT_EQ(Rect(0, 1, 1, 0),
- layerAligned.getTextureCoordinates());
+ EXPECT_EQ(Rect(0, 1, 1, 0), layerAligned.getTextureCoordinates());
OffscreenBuffer layerUnaligned(renderThread.renderState(), Caches::getInstance(), 200u, 225u);
- EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
- layerUnaligned.getTextureCoordinates());
+ EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0), layerUnaligned.getTextureCoordinates());
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(OffscreenBuffer, dirty) {
@@ -221,7 +219,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(OffscreenBufferPool, putAndDestroy) {
auto hugeLayer = pool.get(renderThread.renderState(), pool.getMaxSize() / 64, 64);
EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize());
pool.putOrDelete(hugeLayer);
- EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
+ EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(OffscreenBufferPool, clear) {
@@ -244,4 +242,3 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(OffscreenBufferPool, clear) {
EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
}
-
diff --git a/libs/hwui/tests/unit/OpDumperTests.cpp b/libs/hwui/tests/unit/OpDumperTests.cpp
index 01840d72b766..ef30e872a7bd 100644
--- a/libs/hwui/tests/unit/OpDumperTests.cpp
+++ b/libs/hwui/tests/unit/OpDumperTests.cpp
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
-#include "tests/common/TestUtils.h"
#include "OpDumper.h"
+#include "tests/common/TestUtils.h"
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/tests/unit/PathInterpolatorTests.cpp b/libs/hwui/tests/unit/PathInterpolatorTests.cpp
index d7cb23a4b793..d888012a80ce 100644
--- a/libs/hwui/tests/unit/PathInterpolatorTests.cpp
+++ b/libs/hwui/tests/unit/PathInterpolatorTests.cpp
@@ -37,55 +37,36 @@ const static TestData sTestDataSet[] = {
{0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f},
},
- {
- {
- 0.0f, 0.5f, 0.5178955f, 0.5341797f, 0.5489991f, 0.5625f, 0.5748291f,
- 0.5861328f, 0.60625005f, 0.62402344f, 0.640625f, 0.675f, 0.6951172f,
- 0.71875f, 0.7470703f, 0.78125f, 0.82246095f, 0.84606934f, 0.871875f,
- 0.9000244f, 0.93066406f, 0.96394044f, 1.0f
- },
- {
- 0.0f, 0.0f, 0.0028686523f, 0.011230469f, 0.024719238f, 0.04296875f,
- 0.06561279f, 0.092285156f, 0.15625f, 0.2319336f, 0.31640625f, 0.5f,
- 0.5932617f, 0.68359375f, 0.7680664f, 0.84375f, 0.90771484f, 0.9343872f,
- 0.95703125f, 0.97528076f, 0.98876953f, 0.99713135f, 1.0f
- },
- {
- 0.0f, 0.03375840187072754f, 0.13503384590148926f, 0.23630905151367188f,
- 0.336834192276001f, 0.4508626461029053f, 0.564141035079956f,
- 0.6781694889068604f, 0.7921979427337646f, 0.9054763317108154f, 1.0f
- },
- {
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0459827296435833f,
- 0.5146934390068054f, 0.8607426285743713f, 0.9776809215545654f, 1.0f
+ {{0.0f, 0.5f, 0.5178955f, 0.5341797f, 0.5489991f, 0.5625f,
+ 0.5748291f, 0.5861328f, 0.60625005f, 0.62402344f, 0.640625f, 0.675f,
+ 0.6951172f, 0.71875f, 0.7470703f, 0.78125f, 0.82246095f, 0.84606934f,
+ 0.871875f, 0.9000244f, 0.93066406f, 0.96394044f, 1.0f},
+ {0.0f, 0.0f, 0.0028686523f, 0.011230469f, 0.024719238f, 0.04296875f,
+ 0.06561279f, 0.092285156f, 0.15625f, 0.2319336f, 0.31640625f, 0.5f,
+ 0.5932617f, 0.68359375f, 0.7680664f, 0.84375f, 0.90771484f, 0.9343872f,
+ 0.95703125f, 0.97528076f, 0.98876953f, 0.99713135f, 1.0f},
+ {0.0f, 0.03375840187072754f, 0.13503384590148926f, 0.23630905151367188f,
+ 0.336834192276001f, 0.4508626461029053f, 0.564141035079956f, 0.6781694889068604f,
+ 0.7921979427337646f, 0.9054763317108154f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0459827296435833f, 0.5146934390068054f,
+ 0.8607426285743713f, 0.9776809215545654f, 1.0f
- }
+ }
},
- {
- {
- 0.0f, 0.017895509f, 0.034179688f, 0.048999026f, 0.0625f, 0.0748291f,
- 0.08613282f, 0.10625f, 0.12402344f, 0.140625f, 0.17500001f, 0.19511719f,
- 0.21875f, 0.24707031f, 0.28125f, 0.32246095f, 0.34606934f, 0.371875f,
- 0.4000244f, 0.43066406f, 0.46394044f, 0.5f, 1.0f
- },
- {
- 0.0f, 0.0028686523f, 0.011230469f, 0.024719238f, 0.04296875f, 0.06561279f,
- 0.092285156f, 0.15625f, 0.2319336f, 0.31640625f, 0.5f, 0.5932617f,
- 0.68359375f, 0.7680664f, 0.84375f, 0.90771484f, 0.9343872f, 0.95703125f,
- 0.97528076f, 0.98876953f, 0.99713135f, 1.0f, 1.0f
- },
- {
- 0.0f, 0.102020263671875f, 0.20330810546875f, 0.3165740966796875f,
- 0.43060302734375f, 0.5318756103515625f, 0.6331634521484375f,
- 0.746429443359375f, 0.84771728515625f, 0.9617462158203125f, 1.0f
- },
- {
- 0.0f, 0.14280107617378235f, 0.6245699524879456f, 0.8985776901245117f,
- 0.9887426495552063f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
- }
- },
-
+ {{0.0f, 0.017895509f, 0.034179688f, 0.048999026f, 0.0625f, 0.0748291f,
+ 0.08613282f, 0.10625f, 0.12402344f, 0.140625f, 0.17500001f, 0.19511719f,
+ 0.21875f, 0.24707031f, 0.28125f, 0.32246095f, 0.34606934f, 0.371875f,
+ 0.4000244f, 0.43066406f, 0.46394044f, 0.5f, 1.0f},
+ {0.0f, 0.0028686523f, 0.011230469f, 0.024719238f, 0.04296875f, 0.06561279f,
+ 0.092285156f, 0.15625f, 0.2319336f, 0.31640625f, 0.5f, 0.5932617f,
+ 0.68359375f, 0.7680664f, 0.84375f, 0.90771484f, 0.9343872f, 0.95703125f,
+ 0.97528076f, 0.98876953f, 0.99713135f, 1.0f, 1.0f},
+ {0.0f, 0.102020263671875f, 0.20330810546875f, 0.3165740966796875f, 0.43060302734375f,
+ 0.5318756103515625f, 0.6331634521484375f, 0.746429443359375f, 0.84771728515625f,
+ 0.9617462158203125f, 1.0f},
+ {0.0f, 0.14280107617378235f, 0.6245699524879456f, 0.8985776901245117f, 0.9887426495552063f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}},
};
@@ -98,13 +79,12 @@ static std::vector<float> getY(const TestData& data) {
}
TEST(Interpolator, pathInterpolation) {
- for (const TestData& data: sTestDataSet) {
+ for (const TestData& data : sTestDataSet) {
PathInterpolator interpolator(getX(data), getY(data));
for (size_t i = 0; i < data.inFraction.size(); i++) {
EXPECT_FLOAT_EQ(data.outFraction[i], interpolator.interpolate(data.inFraction[i]));
}
}
}
-
}
}
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index d36bca031a87..8a9e34f81c6d 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -32,7 +32,7 @@ namespace android {
namespace uirenderer {
static void playbackOps(const DisplayList& displayList,
- std::function<void(const RecordedOp&)> opReceiver) {
+ std::function<void(const RecordedOp&)> opReceiver) {
for (auto& chunk : displayList.getChunks()) {
for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
RecordedOp* op = displayList.getOps()[opIndex];
@@ -42,7 +42,7 @@ static void playbackOps(const DisplayList& displayList,
}
static void validateSingleOp(std::unique_ptr<DisplayList>& dl,
- std::function<void(const RecordedOp& op)> opValidator) {
+ std::function<void(const RecordedOp& op)> opValidator) {
ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
opValidator(*(dl->getOps()[0]));
}
@@ -82,7 +82,7 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, emptyClipRect) {
canvas.save(SaveFlags::MatrixClip);
canvas.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
canvas.clipRect(100, 100, 200, 200, SkClipOp::kIntersect);
- canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
+ canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
canvas.restore();
});
ASSERT_EQ(0u, dl->getOps().size()) << "Must be zero ops. Rect should be rejected.";
@@ -120,16 +120,16 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawArc) {
EXPECT_EQ(RecordedOpId::ArcOp, ops[0]->opId);
EXPECT_EQ(Rect(200, 200), ops[0]->unmappedBounds);
- EXPECT_EQ(RecordedOpId::OvalOp, ops[1]->opId)
- << "Circular arcs should be converted to ovals";
+ EXPECT_EQ(RecordedOpId::OvalOp, ops[1]->opId) << "Circular arcs should be converted to ovals";
EXPECT_EQ(Rect(100, 100), ops[1]->unmappedBounds);
}
OPENGL_PIPELINE_TEST(RecordingCanvas, drawLines) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
SkPaint paint;
- paint.setStrokeWidth(20); // doesn't affect recorded bounds - would be resolved at bake time
- float points[] = { 0, 0, 20, 10, 30, 40, 90 }; // NB: only 1 valid line
+ paint.setStrokeWidth(
+ 20); // doesn't affect recorded bounds - would be resolved at bake time
+ float points[] = {0, 0, 20, 10, 30, 40, 90}; // NB: only 1 valid line
canvas.drawLines(&points[0], 7, paint);
});
@@ -143,9 +143,8 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawLines) {
}
OPENGL_PIPELINE_TEST(RecordingCanvas, drawRect) {
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
- canvas.drawRect(10, 20, 90, 180, SkPaint());
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 100, 200, [](RecordingCanvas& canvas) { canvas.drawRect(10, 20, 90, 180, SkPaint()); });
ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
auto op = *(dl->getOps()[0]);
@@ -168,7 +167,7 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawRoundRect) {
});
ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
ASSERT_EQ(RecordedOpId::RectOp, dl->getOps()[0]->opId)
- << "Non-rounded rects should be converted";
+ << "Non-rounded rects should be converted";
}
OPENGL_PIPELINE_TEST(RecordingCanvas, drawGlyphs) {
@@ -176,7 +175,6 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawGlyphs) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
});
@@ -197,7 +195,6 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawGlyphs_strikeThruAndUnderline) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
uint32_t flags = paint.getFlags();
@@ -221,17 +218,17 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawGlyphs_strikeThruAndUnderline) {
ASSERT_EQ(8u, ops.size());
int index = 0;
- EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId); // no underline or strikethrough
+ EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId); // no underline or strikethrough
EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId);
- EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough only
+ EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough only
EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId);
- EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // underline only
+ EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // underline only
EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId);
- EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // underline
- EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough
+ EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // underline
+ EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough
}
OPENGL_PIPELINE_TEST(RecordingCanvas, drawGlyphs_forceAlignLeft) {
@@ -239,7 +236,6 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawGlyphs_forceAlignLeft) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setTextAlign(SkPaint::kLeft_Align);
TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
paint.setTextAlign(SkPaint::kCenter_Align);
@@ -329,15 +325,14 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, backgroundAndImage) {
}
RENDERTHREAD_OPENGL_PIPELINE_TEST(RecordingCanvas, textureLayer) {
- auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
- SkMatrix::MakeTrans(5, 5));
+ auto layerUpdater =
+ TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5));
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200,
- [&layerUpdater](RecordingCanvas& canvas) {
- canvas.drawLayer(layerUpdater.get());
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 200, 200,
+ [&layerUpdater](RecordingCanvas& canvas) { canvas.drawLayer(layerUpdater.get()); });
- validateSingleOp(dl, [] (const RecordedOp& op) {
+ validateSingleOp(dl, [](const RecordedOp& op) {
ASSERT_EQ(RecordedOpId::TextureLayerOp, op.opId);
ASSERT_TRUE(op.localMatrix.isIdentity()) << "Op must not apply matrix at record time.";
});
@@ -352,26 +347,26 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_simple) {
int count = 0;
playbackOps(*dl, [&count](const RecordedOp& op) {
Matrix4 expectedMatrix;
- switch(count++) {
- case 0:
- EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId);
- EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
- EXPECT_EQ(nullptr, op.localClip);
- EXPECT_TRUE(op.localMatrix.isIdentity());
- break;
- case 1:
- EXPECT_EQ(RecordedOpId::RectOp, op.opId);
- EXPECT_CLIP_RECT(Rect(180, 160), op.localClip);
- EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
- expectedMatrix.loadTranslate(-10, -20, 0);
- EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
- break;
- case 2:
- EXPECT_EQ(RecordedOpId::EndLayerOp, op.opId);
- // Don't bother asserting recording state data - it's not used
- break;
- default:
- ADD_FAILURE();
+ switch (count++) {
+ case 0:
+ EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId);
+ EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
+ EXPECT_EQ(nullptr, op.localClip);
+ EXPECT_TRUE(op.localMatrix.isIdentity());
+ break;
+ case 1:
+ EXPECT_EQ(RecordedOpId::RectOp, op.opId);
+ EXPECT_CLIP_RECT(Rect(180, 160), op.localClip);
+ EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
+ expectedMatrix.loadTranslate(-10, -20, 0);
+ EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
+ break;
+ case 2:
+ EXPECT_EQ(RecordedOpId::EndLayerOp, op.opId);
+ // Don't bother asserting recording state data - it's not used
+ break;
+ default:
+ ADD_FAILURE();
}
});
EXPECT_EQ(3, count);
@@ -379,14 +374,14 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_simple) {
OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_rounding) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
- canvas.saveLayerAlpha(10.25f, 10.75f, 89.25f, 89.75f, 128, SaveFlags::ClipToLayer);
- canvas.drawRect(20, 20, 80, 80, SkPaint());
- canvas.restore();
- });
- int count = 0;
- playbackOps(*dl, [&count](const RecordedOp& op) {
- Matrix4 expectedMatrix;
- switch(count++) {
+ canvas.saveLayerAlpha(10.25f, 10.75f, 89.25f, 89.75f, 128, SaveFlags::ClipToLayer);
+ canvas.drawRect(20, 20, 80, 80, SkPaint());
+ canvas.restore();
+ });
+ int count = 0;
+ playbackOps(*dl, [&count](const RecordedOp& op) {
+ Matrix4 expectedMatrix;
+ switch (count++) {
case 0:
EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId);
EXPECT_EQ(Rect(10, 10, 90, 90), op.unmappedBounds) << "Expect bounds rounded out";
@@ -402,9 +397,9 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_rounding) {
break;
default:
ADD_FAILURE();
- }
- });
- EXPECT_EQ(3, count);
+ }
+ });
+ EXPECT_EQ(3, count);
}
OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_missingRestore) {
@@ -424,31 +419,31 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_missingRestore) {
OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_simpleUnclipped) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
- canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
+ canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
canvas.drawRect(10, 20, 190, 180, SkPaint());
canvas.restore();
});
int count = 0;
playbackOps(*dl, [&count](const RecordedOp& op) {
- switch(count++) {
- case 0:
- EXPECT_EQ(RecordedOpId::BeginUnclippedLayerOp, op.opId);
- EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
- EXPECT_EQ(nullptr, op.localClip);
- EXPECT_TRUE(op.localMatrix.isIdentity());
- break;
- case 1:
- EXPECT_EQ(RecordedOpId::RectOp, op.opId);
- EXPECT_EQ(nullptr, op.localClip);
- EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
- EXPECT_TRUE(op.localMatrix.isIdentity());
- break;
- case 2:
- EXPECT_EQ(RecordedOpId::EndUnclippedLayerOp, op.opId);
- // Don't bother asserting recording state data - it's not used
- break;
- default:
- ADD_FAILURE();
+ switch (count++) {
+ case 0:
+ EXPECT_EQ(RecordedOpId::BeginUnclippedLayerOp, op.opId);
+ EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
+ EXPECT_EQ(nullptr, op.localClip);
+ EXPECT_TRUE(op.localMatrix.isIdentity());
+ break;
+ case 1:
+ EXPECT_EQ(RecordedOpId::RectOp, op.opId);
+ EXPECT_EQ(nullptr, op.localClip);
+ EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
+ EXPECT_TRUE(op.localMatrix.isIdentity());
+ break;
+ case 2:
+ EXPECT_EQ(RecordedOpId::EndUnclippedLayerOp, op.opId);
+ // Don't bother asserting recording state data - it's not used
+ break;
+ default:
+ ADD_FAILURE();
}
});
EXPECT_EQ(3, count);
@@ -458,7 +453,7 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_addClipFlag) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
canvas.clipRect(10, 20, 190, 180, SkClipOp::kIntersect);
- canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
+ canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
canvas.drawRect(10, 20, 190, 180, SkPaint());
canvas.restore();
canvas.restore();
@@ -487,7 +482,7 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_viewportCrop) {
if (count++ == 1) {
Matrix4 expectedMatrix;
EXPECT_EQ(RecordedOpId::RectOp, op.opId);
- EXPECT_CLIP_RECT(Rect(100, 100), op.localClip) // Recorded clip rect should be
+ EXPECT_CLIP_RECT(Rect(100, 100), op.localClip) // Recorded clip rect should be
// intersection of viewport and saveLayer bounds, in layer space;
EXPECT_EQ(Rect(400, 400), op.unmappedBounds);
expectedMatrix.loadTranslate(-100, -100, 0);
@@ -564,7 +559,7 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_rotateClipped) {
OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_rejectBegin) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.translate(0, -20); // avoid identity case
+ canvas.translate(0, -20); // avoid identity case
// empty clip rect should force layer + contents to be rejected
canvas.clipRect(0, -20, 200, -20, SkClipOp::kIntersect);
canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer);
@@ -577,37 +572,38 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, saveLayer_rejectBegin) {
}
OPENGL_PIPELINE_TEST(RecordingCanvas, drawRenderNode_rejection) {
- auto child = TestUtils::createNode(50, 50, 150, 150,
- [](RenderProperties& props, Canvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
-
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&child](RecordingCanvas& canvas) {
- canvas.clipRect(0, 0, 0, 0, SkClipOp::kIntersect); // empty clip, reject node
- canvas.drawRenderNode(child.get()); // shouldn't crash when rejecting node...
- });
+ auto child =
+ TestUtils::createNode(50, 50, 150, 150, [](RenderProperties& props, Canvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
+
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 200, 200, [&child](RecordingCanvas& canvas) {
+ canvas.clipRect(0, 0, 0, 0, SkClipOp::kIntersect); // empty clip, reject node
+ canvas.drawRenderNode(child.get()); // shouldn't crash when rejecting node...
+ });
ASSERT_TRUE(dl->isEmpty());
}
OPENGL_PIPELINE_TEST(RecordingCanvas, drawRenderNode_projection) {
- sp<RenderNode> background = TestUtils::createNode(50, 50, 150, 150,
- [](RenderProperties& props, Canvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
+ sp<RenderNode> background =
+ TestUtils::createNode(50, 50, 150, 150, [](RenderProperties& props, Canvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
{
background->mutateStagingProperties().setProjectionReceiver(false);
// NO RECEIVER PRESENT
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200,
- [&background](RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 100, 100, SkPaint());
- canvas.drawRenderNode(background.get());
- canvas.drawRect(0, 0, 100, 100, SkPaint());
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 200, 200, [&background](RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ canvas.drawRenderNode(background.get());
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ });
EXPECT_EQ(-1, dl->projectionReceiveIndex)
<< "no projection receiver should have been observed";
}
@@ -615,18 +611,17 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawRenderNode_projection) {
background->mutateStagingProperties().setProjectionReceiver(true);
// RECEIVER PRESENT
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200,
- [&background](RecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 100, 100, SkPaint());
- canvas.drawRenderNode(background.get());
- canvas.drawRect(0, 0, 100, 100, SkPaint());
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 200, 200, [&background](RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ canvas.drawRenderNode(background.get());
+ canvas.drawRect(0, 0, 100, 100, SkPaint());
+ });
ASSERT_EQ(3u, dl->getOps().size()) << "Must be three ops";
auto op = dl->getOps()[1];
EXPECT_EQ(RecordedOpId::RenderNodeOp, op->opId);
- EXPECT_EQ(1, dl->projectionReceiveIndex)
- << "correct projection receiver not identified";
+ EXPECT_EQ(1, dl->projectionReceiveIndex) << "correct projection receiver not identified";
// verify the behavior works even though projection receiver hasn't been sync'd yet
EXPECT_TRUE(background->stagingProperties().isProjectionReceiver());
@@ -718,17 +713,18 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, insertReorderBarrier_clip) {
OPENGL_PIPELINE_TEST(RecordingCanvas, refPaint) {
SkPaint paint;
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&paint](RecordingCanvas& canvas) {
- paint.setColor(SK_ColorBLUE);
- // first two should use same paint
- canvas.drawRect(0, 0, 200, 10, paint);
- SkPaint paintCopy(paint);
- canvas.drawRect(0, 10, 200, 20, paintCopy);
-
- // only here do we use different paint ptr
- paint.setColor(SK_ColorRED);
- canvas.drawRect(0, 20, 200, 30, paint);
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 200, 200, [&paint](RecordingCanvas& canvas) {
+ paint.setColor(SK_ColorBLUE);
+ // first two should use same paint
+ canvas.drawRect(0, 0, 200, 10, paint);
+ SkPaint paintCopy(paint);
+ canvas.drawRect(0, 10, 200, 20, paintCopy);
+
+ // only here do we use different paint ptr
+ paint.setColor(SK_ColorRED);
+ canvas.drawRect(0, 20, 200, 30, paint);
+ });
auto ops = dl->getOps();
ASSERT_EQ(3u, ops.size());
@@ -745,56 +741,58 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, refPaint) {
OPENGL_PIPELINE_TEST(RecordingCanvas, refBitmap) {
sk_sp<Bitmap> bitmap(TestUtils::createBitmap(100, 100));
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
- canvas.drawBitmap(*bitmap, 0, 0, nullptr);
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 100, 100,
+ [&bitmap](RecordingCanvas& canvas) { canvas.drawBitmap(*bitmap, 0, 0, nullptr); });
auto& bitmaps = dl->getBitmapResources();
EXPECT_EQ(1u, bitmaps.size());
}
OPENGL_PIPELINE_TEST(RecordingCanvas, refBitmapInShader_bitmapShader) {
sk_sp<Bitmap> bitmap = TestUtils::createBitmap(100, 100);
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
- SkPaint paint;
- SkBitmap skBitmap;
- bitmap->getSkBitmap(&skBitmap);
- sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
- sk_sp<SkShader> shader = image->makeShader(
- SkShader::TileMode::kClamp_TileMode,
- SkShader::TileMode::kClamp_TileMode,
- nullptr);
- paint.setShader(std::move(shader));
- canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 100, 100, [&bitmap](RecordingCanvas& canvas) {
+ SkPaint paint;
+ SkBitmap skBitmap;
+ bitmap->getSkBitmap(&skBitmap);
+ sk_sp<SkImage> image =
+ SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+ sk_sp<SkShader> shader =
+ image->makeShader(SkShader::TileMode::kClamp_TileMode,
+ SkShader::TileMode::kClamp_TileMode, nullptr);
+ paint.setShader(std::move(shader));
+ canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
+ });
auto& bitmaps = dl->getBitmapResources();
EXPECT_EQ(1u, bitmaps.size());
}
OPENGL_PIPELINE_TEST(RecordingCanvas, refBitmapInShader_composeShader) {
sk_sp<Bitmap> bitmap = TestUtils::createBitmap(100, 100);
- auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
- SkPaint paint;
- SkBitmap skBitmap;
- bitmap->getSkBitmap(&skBitmap);
- sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
- sk_sp<SkShader> shader1 = image->makeShader(
- SkShader::TileMode::kClamp_TileMode,
- SkShader::TileMode::kClamp_TileMode,
- nullptr);
-
- SkPoint center;
- center.set(50, 50);
- SkColor colors[2];
- colors[0] = Color::Black;
- colors[1] = Color::White;
- sk_sp<SkShader> shader2 = SkGradientShader::MakeRadial(center, 50, colors, nullptr, 2,
- SkShader::TileMode::kRepeat_TileMode);
-
- sk_sp<SkShader> composeShader = SkShader::MakeComposeShader(std::move(shader1), std::move(shader2),
- SkBlendMode::kMultiply);
- paint.setShader(std::move(composeShader));
- canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
- });
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(
+ 100, 100, [&bitmap](RecordingCanvas& canvas) {
+ SkPaint paint;
+ SkBitmap skBitmap;
+ bitmap->getSkBitmap(&skBitmap);
+ sk_sp<SkImage> image =
+ SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+ sk_sp<SkShader> shader1 =
+ image->makeShader(SkShader::TileMode::kClamp_TileMode,
+ SkShader::TileMode::kClamp_TileMode, nullptr);
+
+ SkPoint center;
+ center.set(50, 50);
+ SkColor colors[2];
+ colors[0] = Color::Black;
+ colors[1] = Color::White;
+ sk_sp<SkShader> shader2 = SkGradientShader::MakeRadial(
+ center, 50, colors, nullptr, 2, SkShader::TileMode::kRepeat_TileMode);
+
+ sk_sp<SkShader> composeShader = SkShader::MakeComposeShader(
+ std::move(shader1), std::move(shader2), SkBlendMode::kMultiply);
+ paint.setShader(std::move(composeShader));
+ canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
+ });
auto& bitmaps = dl->getBitmapResources();
EXPECT_EQ(1u, bitmaps.size());
}
@@ -804,9 +802,7 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawText) {
Paint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- std::unique_ptr<uint16_t[]> dst = TestUtils::asciiToUtf16("HELLO");
- canvas.drawText(dst.get(), 0, 5, 5, 25, 25, minikin::kBidi_Force_LTR, paint, NULL);
+ TestUtils::drawUtf8ToCanvas(&canvas, "HELLO", paint, 25, 25);
});
int count = 0;
@@ -822,16 +818,15 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawText) {
}
OPENGL_PIPELINE_TEST(RecordingCanvas, drawTextInHighContrast) {
+ Properties::enableHighContrastText = true;
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
- canvas.setHighContrastText(true);
Paint paint;
paint.setColor(SK_ColorWHITE);
paint.setAntiAlias(true);
paint.setTextSize(20);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- std::unique_ptr<uint16_t[]> dst = TestUtils::asciiToUtf16("HELLO");
- canvas.drawText(dst.get(), 0, 5, 5, 25, 25, minikin::kBidi_Force_LTR, paint, NULL);
+ TestUtils::drawUtf8ToCanvas(&canvas, "HELLO", paint, 25, 25);
});
+ Properties::enableHighContrastText = false;
int count = 0;
playbackOps(*dl, [&count](const RecordedOp& op) {
@@ -848,5 +843,5 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawTextInHighContrast) {
ASSERT_EQ(2, count);
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 4c3e182ced2f..15c0ab1ad8d2 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -14,24 +14,24 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
#include <VectorDrawable.h>
+#include <gtest/gtest.h>
+#include <SkClipStack.h>
+#include <SkLiteRecorder.h>
+#include <SkSurface_Base.h>
+#include <string.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
+#include "FatalTestCanvas.h"
#include "IContextFactory.h"
+#include "SkiaCanvas.h"
#include "pipeline/skia/SkiaDisplayList.h"
+#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "pipeline/skia/SkiaPipeline.h"
#include "pipeline/skia/SkiaRecordingCanvas.h"
#include "renderthread/CanvasContext.h"
#include "tests/common/TestUtils.h"
-#include "SkiaCanvas.h"
-#include <SkSurface_Base.h>
-#include <SkLiteRecorder.h>
-#include <SkClipStack.h>
-#include "FatalTestCanvas.h"
-#include <string.h>
-
using namespace android;
using namespace android::uirenderer;
@@ -39,8 +39,8 @@ using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::skiapipeline;
TEST(RenderNodeDrawable, create) {
- auto rootNode = TestUtils::createNode(0, 0, 200, 400,
- [](RenderProperties& props, Canvas& canvas) {
+ auto rootNode =
+ TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
});
@@ -65,47 +65,50 @@ static void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
}
static void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) {
- auto node = TestUtils::createSkiaNode(0, 0, 100, 100,
+ auto node = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
[expectedDrawOrder, z](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedRect(&canvas, expectedDrawOrder);
- props.setTranslationZ(z);
- });
- canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
+ drawOrderedRect(&canvas, expectedDrawOrder);
+ props.setTranslationZ(z);
+ });
+ canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
}
-static void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder,
+static void drawOrderedNode(
+ Canvas* canvas, uint8_t expectedDrawOrder,
std::function<void(RenderProperties& props, SkiaRecordingCanvas& canvas)> setup) {
- auto node = TestUtils::createSkiaNode(0, 0, 100, 100,
+ auto node = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
[expectedDrawOrder, setup](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedRect(&canvas, expectedDrawOrder);
- if (setup) {
- setup(props, canvas);
- }
- });
- canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
+ drawOrderedRect(&canvas, expectedDrawOrder);
+ if (setup) {
+ setup(props, canvas);
+ }
+ });
+ canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
}
class ZReorderCanvas : public SkCanvas {
public:
ZReorderCanvas(int width, int height) : SkCanvas(width, height) {}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
- int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel
+ int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel
EXPECT_EQ(expectedOrder, mDrawCounter++) << "An op was drawn out of order";
}
int getIndex() { return mDrawCounter; }
+
protected:
int mDrawCounter = 0;
};
-} // end anonymous namespace
+} // end anonymous namespace
TEST(RenderNodeDrawable, zReorder) {
-
- auto parent = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ auto parent = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
canvas.insertReorderBarrier(true);
canvas.insertReorderBarrier(false);
- drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
+ drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
drawOrderedRect(&canvas, 1);
canvas.insertReorderBarrier(true);
drawOrderedNode(&canvas, 6, 2.0f);
@@ -116,37 +119,36 @@ TEST(RenderNodeDrawable, zReorder) {
drawOrderedNode(&canvas, 7, 2.0f);
canvas.insertReorderBarrier(false);
drawOrderedRect(&canvas, 8);
- drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
- canvas.insertReorderBarrier(true); //reorder a node ahead of drawrect op
+ drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
+ canvas.insertReorderBarrier(true); // reorder a node ahead of drawrect op
drawOrderedRect(&canvas, 11);
drawOrderedNode(&canvas, 10, -1.0f);
canvas.insertReorderBarrier(false);
- canvas.insertReorderBarrier(true); //test with two empty reorder sections
+ canvas.insertReorderBarrier(true); // test with two empty reorder sections
canvas.insertReorderBarrier(true);
canvas.insertReorderBarrier(false);
drawOrderedRect(&canvas, 12);
});
- //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+ // create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
ZReorderCanvas canvas(100, 100);
RenderNodeDrawable drawable(parent.get(), &canvas, false);
canvas.drawDrawable(&drawable);
EXPECT_EQ(13, canvas.getIndex());
}
-TEST(RenderNodeDrawable, composeOnLayer)
-{
+TEST(RenderNodeDrawable, composeOnLayer) {
auto surface = SkSurface::MakeRasterN32Premul(1, 1);
SkCanvas& canvas = *surface->getCanvas();
canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1,
- [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
- recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
- });
+ auto rootNode = TestUtils::createSkiaNode(
+ 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
+ recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+ });
- //attach a layer to the render node
+ // attach a layer to the render node
auto surfaceLayer = SkSurface::MakeRasterN32Premul(1, 1);
auto canvas2 = surfaceLayer->getCanvas();
canvas2->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
@@ -181,39 +183,38 @@ static SkMatrix getRecorderMatrix(const SkiaRecordingCanvas& recorder) {
}
}
-TEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore)
-{
+TEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore) {
auto surface = SkSurface::MakeRasterN32Premul(400, 800);
SkCanvas& canvas = *surface->getCanvas();
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
- auto rootNode = TestUtils::createSkiaNode(0, 0, 400, 800,
- [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
- SkPaint layerPaint;
- ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder));
- EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());
+ auto rootNode = TestUtils::createSkiaNode(
+ 0, 0, 400, 800, [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
+ SkPaint layerPaint;
+ ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder));
+ EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());
- //note we don't pass SaveFlags::MatrixClip, but matrix and clip will be saved
- recorder.saveLayer(0, 0, 400, 400, &layerPaint, SaveFlags::ClipToLayer);
- ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 400), getRecorderClipBounds(recorder));
- EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());
+ // note we don't pass SaveFlags::MatrixClip, but matrix and clip will be saved
+ recorder.saveLayer(0, 0, 400, 400, &layerPaint, SaveFlags::ClipToLayer);
+ ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 400), getRecorderClipBounds(recorder));
+ EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());
- recorder.clipRect(50, 50, 350, 350, SkClipOp::kIntersect);
- ASSERT_EQ(SkRect::MakeLTRB(50, 50, 350, 350), getRecorderClipBounds(recorder));
+ recorder.clipRect(50, 50, 350, 350, SkClipOp::kIntersect);
+ ASSERT_EQ(SkRect::MakeLTRB(50, 50, 350, 350), getRecorderClipBounds(recorder));
- recorder.translate(300.0f, 400.0f);
- EXPECT_EQ(SkMatrix::MakeTrans(300.0f, 400.0f), getRecorderMatrix(recorder));
+ recorder.translate(300.0f, 400.0f);
+ EXPECT_EQ(SkMatrix::MakeTrans(300.0f, 400.0f), getRecorderMatrix(recorder));
- recorder.restore();
- ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder));
- EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());
+ recorder.restore();
+ ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder));
+ EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(SK_ColorGREEN);
- recorder.drawRect(0.0f, 400.0f, 400.0f, 800.0f, paint);
- });
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(SK_ColorGREEN);
+ recorder.drawRect(0.0f, 400.0f, 400.0f, 800.0f, paint);
+ });
RenderNodeDrawable drawable(rootNode.get(), &canvas, true);
canvas.drawDrawable(&drawable);
@@ -227,7 +228,7 @@ public:
return new AnimationContext(clock);
}
};
-} // end anonymous namespace
+} // end anonymous namespace
RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorder) {
static const int SCROLL_X = 5;
@@ -237,33 +238,36 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorder) {
ProjectionTestCanvas(int width, int height) : SkCanvas(width, height) {}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
const int index = mDrawCounter++;
- SkMatrix expectedMatrix;;
+ SkMatrix expectedMatrix;
+ ;
switch (index) {
- case 0: //this is node "B"
- EXPECT_EQ(SkRect::MakeWH(100, 100), rect);
- EXPECT_EQ(SK_ColorWHITE, paint.getColor());
- expectedMatrix.reset();
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, 100, 100), TestUtils::getClipBounds(this));
- break;
- case 1: //this is node "P"
- EXPECT_EQ(SkRect::MakeLTRB(-10, -10, 60, 60), rect);
- EXPECT_EQ(SK_ColorDKGRAY, paint.getColor());
- expectedMatrix.setTranslate(50 - SCROLL_X, 50 - SCROLL_Y);
- EXPECT_EQ(SkRect::MakeLTRB(-35, -30, 45, 50), TestUtils::getLocalClipBounds(this));
- break;
- case 2: //this is node "C"
- EXPECT_EQ(SkRect::MakeWH(100, 50), rect);
- EXPECT_EQ(SK_ColorBLUE, paint.getColor());
- expectedMatrix.setTranslate(-SCROLL_X, 50 - SCROLL_Y);
- EXPECT_EQ(SkRect::MakeLTRB(0, 40, 95, 90), TestUtils::getClipBounds(this));
- break;
- default:
- ADD_FAILURE();
+ case 0: // this is node "B"
+ EXPECT_EQ(SkRect::MakeWH(100, 100), rect);
+ EXPECT_EQ(SK_ColorWHITE, paint.getColor());
+ expectedMatrix.reset();
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, 100, 100), TestUtils::getClipBounds(this));
+ break;
+ case 1: // this is node "P"
+ EXPECT_EQ(SkRect::MakeLTRB(-10, -10, 60, 60), rect);
+ EXPECT_EQ(SK_ColorDKGRAY, paint.getColor());
+ expectedMatrix.setTranslate(50 - SCROLL_X, 50 - SCROLL_Y);
+ EXPECT_EQ(SkRect::MakeLTRB(-35, -30, 45, 50),
+ TestUtils::getLocalClipBounds(this));
+ break;
+ case 2: // this is node "C"
+ EXPECT_EQ(SkRect::MakeWH(100, 50), rect);
+ EXPECT_EQ(SK_ColorBLUE, paint.getColor());
+ expectedMatrix.setTranslate(-SCROLL_X, 50 - SCROLL_Y);
+ EXPECT_EQ(SkRect::MakeLTRB(0, 40, 95, 90), TestUtils::getClipBounds(this));
+ break;
+ default:
+ ADD_FAILURE();
}
EXPECT_EQ(expectedMatrix, getTotalMatrix());
}
int getIndex() { return mDrawCounter; }
+
protected:
int mDrawCounter = 0;
};
@@ -276,66 +280,143 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorder) {
* The parent is scrolled by SCROLL_X/SCROLL_Y, but this does not affect the background
* (which isn't affected by scroll).
*/
- auto receiverBackground = TestUtils::createSkiaNode(0, 0, 100, 100,
+ auto receiverBackground = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
[](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- properties.setProjectionReceiver(true);
- // scroll doesn't apply to background, so undone via translationX/Y
- // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
- properties.setTranslationX(SCROLL_X);
- properties.setTranslationY(SCROLL_Y);
-
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- }, "B");
-
- auto projectingRipple = TestUtils::createSkiaNode(50, 0, 100, 50,
+ properties.setProjectionReceiver(true);
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj
+ // receiver!
+ properties.setTranslationX(SCROLL_X);
+ properties.setTranslationY(SCROLL_Y);
+
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ },
+ "B");
+
+ auto projectingRipple = TestUtils::createSkiaNode(
+ 50, 0, 100, 50,
[](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- properties.setProjectBackwards(true);
- properties.setClipToBounds(false);
- SkPaint paint;
- paint.setColor(SK_ColorDKGRAY);
- canvas.drawRect(-10, -10, 60, 60, paint);
- }, "P");
- auto child = TestUtils::createSkiaNode(0, 50, 100, 100,
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(-10, -10, 60, 60, paint);
+ },
+ "P");
+ auto child = TestUtils::createSkiaNode(
+ 0, 50, 100, 100,
[&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorBLUE);
- canvas.drawRect(0, 0, 100, 50, paint);
- canvas.drawRenderNode(projectingRipple.get());
- }, "C");
- auto parent = TestUtils::createSkiaNode(0, 0, 100, 100,
- [&receiverBackground, &child](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- // Set a rect outline for the projecting ripple to be masked against.
- properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
-
- canvas.save(SaveFlags::MatrixClip);
- canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
- canvas.drawRenderNode(receiverBackground.get());
- canvas.drawRenderNode(child.get());
- canvas.restore();
- }, "A");
+ SkPaint paint;
+ paint.setColor(SK_ColorBLUE);
+ canvas.drawRect(0, 0, 100, 50, paint);
+ canvas.drawRenderNode(projectingRipple.get());
+ },
+ "C");
+ auto parent = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
+ [&receiverBackground, &child](RenderProperties& properties,
+ SkiaRecordingCanvas& canvas) {
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
+
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.translate(-SCROLL_X,
+ -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ canvas.restore();
+ },
+ "A");
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, parent.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
parent->prepareTree(info);
- //parent(A) -> (receiverBackground, child)
- //child(C) -> (rect[0, 0, 100, 50], projectingRipple)
- //projectingRipple(P) -> (rect[-10, -10, 60, 60]) -> projects backwards
- //receiverBackground(B) -> (rect[0, 0, 100, 100]) -> projection receiver
+ // parent(A) -> (receiverBackground, child)
+ // child(C) -> (rect[0, 0, 100, 50], projectingRipple)
+ // projectingRipple(P) -> (rect[-10, -10, 60, 60]) -> projects backwards
+ // receiverBackground(B) -> (rect[0, 0, 100, 100]) -> projection receiver
- //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+ // create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
ProjectionTestCanvas canvas(100, 100);
RenderNodeDrawable drawable(parent.get(), &canvas, true);
canvas.drawDrawable(&drawable);
EXPECT_EQ(3, canvas.getIndex());
}
-RENDERTHREAD_TEST(RenderNodeDrawable, projectionHwLayer) {
+RENDERTHREAD_SKIA_PIPELINE_TEST(RenderNodeDrawable, emptyReceiver) {
+ class ProjectionTestCanvas : public SkCanvas {
+ public:
+ ProjectionTestCanvas(int width, int height) : SkCanvas(width, height) {}
+ void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+ mDrawCounter++;
+ }
+
+ int getDrawCounter() { return mDrawCounter; }
+
+ private:
+ int mDrawCounter = 0;
+ };
+
+ auto receiverBackground = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
+ [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ },
+ "B"); // a receiver with an empty display list
+
+ auto projectingRipple = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
+ [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ SkPaint paint;
+ canvas.drawRect(0, 0, 100, 100, paint);
+ },
+ "P");
+ auto child = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
+ [&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+ SkPaint paint;
+ canvas.drawRect(0, 0, 100, 100, paint);
+ canvas.drawRenderNode(projectingRipple.get());
+ },
+ "C");
+ auto parent = TestUtils::createSkiaNode(
+ 0, 0, 100, 100,
+ [&receiverBackground, &child](RenderProperties& properties,
+ SkiaRecordingCanvas& canvas) {
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ },
+ "A");
+ ContextFactory contextFactory;
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
+ TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+ DamageAccumulator damageAccumulator;
+ info.damageAccumulator = &damageAccumulator;
+ parent->prepareTree(info);
+
+ // parent(A) -> (receiverBackground, child)
+ // child(C) -> (rect[0, 0, 100, 100], projectingRipple)
+ // projectingRipple(P) -> (rect[0, 0, 100, 100]) -> projects backwards
+ // receiverBackground(B) -> (empty) -> projection receiver
+
+ // create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+ ProjectionTestCanvas canvas(100, 100);
+ RenderNodeDrawable drawable(parent.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(2, canvas.getDrawCounter());
+}
+
+RENDERTHREAD_SKIA_PIPELINE_TEST(RenderNodeDrawable, projectionHwLayer) {
/* R is backward projected on B and C is a layer.
A
/ \
@@ -352,17 +433,17 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionHwLayer) {
class ProjectionTestCanvas : public SkCanvas {
public:
ProjectionTestCanvas(int* drawCounter)
- : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT)
- , mDrawCounter(drawCounter)
- {}
+ : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT), mDrawCounter(drawCounter) {}
void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
- const SkPaint&) override {
- EXPECT_EQ(0, (*mDrawCounter)++); //part of painting the layer
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, LAYER_WIDTH, LAYER_HEIGHT), TestUtils::getClipBounds(this));
+ const SkPaint&) override {
+ EXPECT_EQ(0, (*mDrawCounter)++); // part of painting the layer
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, LAYER_WIDTH, LAYER_HEIGHT),
+ TestUtils::getClipBounds(this));
}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
EXPECT_EQ(1, (*mDrawCounter)++);
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this));
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT),
+ TestUtils::getClipBounds(this));
}
void onDrawOval(const SkRect&, const SkPaint&) override {
EXPECT_EQ(2, (*mDrawCounter)++);
@@ -377,69 +458,74 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionHwLayer) {
class ProjectionLayer : public SkSurface_Base {
public:
ProjectionLayer(int* drawCounter)
- : SkSurface_Base(SkImageInfo::MakeN32Premul(LAYER_WIDTH, LAYER_HEIGHT), nullptr)
- , mDrawCounter(drawCounter) {
- }
- void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {
+ : SkSurface_Base(SkImageInfo::MakeN32Premul(LAYER_WIDTH, LAYER_HEIGHT), nullptr)
+ , mDrawCounter(drawCounter) {}
+ virtual sk_sp<SkImage> onNewImageSnapshot() override {
EXPECT_EQ(3, (*mDrawCounter)++);
EXPECT_EQ(SkRect::MakeLTRB(100 - SCROLL_X, 100 - SCROLL_Y, 300 - SCROLL_X,
- 300 - SCROLL_Y), TestUtils::getClipBounds(this->getCanvas()));
- }
- SkCanvas* onNewCanvas() override {
- return new ProjectionTestCanvas(mDrawCounter);
- }
- sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
- return nullptr;
- }
- sk_sp<SkImage> onNewImageSnapshot() override {
+ 300 - SCROLL_Y),
+ TestUtils::getClipBounds(this->getCanvas()));
return nullptr;
}
+ SkCanvas* onNewCanvas() override { return new ProjectionTestCanvas(mDrawCounter); }
+ sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
void onCopyOnWrite(ContentChangeMode) override {}
int* mDrawCounter;
+ void onWritePixels(const SkPixmap&, int x, int y) {}
};
- auto receiverBackground = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ auto receiverBackground = TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- properties.setProjectionReceiver(true);
- // scroll doesn't apply to background, so undone via translationX/Y
- // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
- properties.setTranslationX(SCROLL_X);
- properties.setTranslationY(SCROLL_Y);
-
- canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
- }, "B"); //B
- auto projectingRipple = TestUtils::createSkiaNode(0, 0, LAYER_WIDTH, LAYER_HEIGHT,
+ properties.setProjectionReceiver(true);
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj
+ // receiver!
+ properties.setTranslationX(SCROLL_X);
+ properties.setTranslationY(SCROLL_Y);
+
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
+ },
+ "B"); // B
+ auto projectingRipple = TestUtils::createSkiaNode(
+ 0, 0, LAYER_WIDTH, LAYER_HEIGHT,
[](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- properties.setProjectBackwards(true);
- properties.setClipToBounds(false);
- canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
- }, "R"); //R
- auto child = TestUtils::createSkiaNode(100, 100, 300, 300,
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
+ },
+ "R"); // R
+ auto child = TestUtils::createSkiaNode(
+ 100, 100, 300, 300,
[&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- canvas.drawRenderNode(projectingRipple.get());
- canvas.drawArc(0, 0, LAYER_WIDTH, LAYER_HEIGHT, 0.0f, 280.0f, true, SkPaint());
- }, "C"); //C
- auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ canvas.drawRenderNode(projectingRipple.get());
+ canvas.drawArc(0, 0, LAYER_WIDTH, LAYER_HEIGHT, 0.0f, 280.0f, true, SkPaint());
+ },
+ "C"); // C
+ auto parent = TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[&receiverBackground, &child](RenderProperties& properties,
- SkiaRecordingCanvas& canvas) {
- // Set a rect outline for the projecting ripple to be masked against.
- properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
- canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
- canvas.drawRenderNode(receiverBackground.get());
- canvas.drawRenderNode(child.get());
- }, "A"); //A
-
- //prepareTree is required to find, which receivers have backward projected nodes
+ SkiaRecordingCanvas& canvas) {
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
+ canvas.translate(-SCROLL_X,
+ -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ },
+ "A"); // A
+
+ // prepareTree is required to find, which receivers have backward projected nodes
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, parent.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
parent->prepareTree(info);
int drawCounter = 0;
- //set a layer after prepareTree to avoid layer logic there
+ // set a layer after prepareTree to avoid layer logic there
child->animatorProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
sk_sp<SkSurface> surfaceLayer1(new ProjectionLayer(&drawCounter));
child->setLayerSurface(surfaceLayer1);
@@ -449,9 +535,10 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionHwLayer) {
LayerUpdateQueue layerUpdateQueue;
layerUpdateQueue.enqueueLayerWithDamage(child.get(),
- android::uirenderer::Rect(LAYER_WIDTH, LAYER_HEIGHT));
- SkiaPipeline::renderLayersImpl(layerUpdateQueue, true, false);
- EXPECT_EQ(1, drawCounter); //assert index 0 is drawn on the layer
+ android::uirenderer::Rect(LAYER_WIDTH, LAYER_HEIGHT));
+ auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ pipeline->renderLayersImpl(layerUpdateQueue, true, false);
+ EXPECT_EQ(1, drawCounter); // assert index 0 is drawn on the layer
RenderNodeDrawable drawable(parent.get(), surfaceLayer1->getCanvas(), true);
surfaceLayer1->getCanvas()->drawDrawable(&drawable);
@@ -488,40 +575,50 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionChildScroll) {
int mDrawCounter = 0;
};
- auto receiverBackground = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ auto receiverBackground = TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- properties.setProjectionReceiver(true);
- canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
- }, "B"); //B
- auto projectingRipple = TestUtils::createSkiaNode(0, 0, 200, 200,
+ properties.setProjectionReceiver(true);
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
+ },
+ "B"); // B
+ auto projectingRipple = TestUtils::createSkiaNode(
+ 0, 0, 200, 200,
[](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- // scroll doesn't apply to background, so undone via translationX/Y
- // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
- properties.setTranslationX(SCROLL_X);
- properties.setTranslationY(SCROLL_Y);
- properties.setProjectBackwards(true);
- properties.setClipToBounds(false);
- canvas.drawOval(0, 0, 200, 200, SkPaint());
- }, "R"); //R
- auto child = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj
+ // receiver!
+ properties.setTranslationX(SCROLL_X);
+ properties.setTranslationY(SCROLL_Y);
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(0, 0, 200, 200, SkPaint());
+ },
+ "R"); // R
+ auto child = TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
- // Record time clip will be ignored by projectee
- canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
-
- canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
- canvas.drawRenderNode(projectingRipple.get());
- }, "C"); //C
- auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
- [&receiverBackground, &child](RenderProperties& properties,
- SkiaRecordingCanvas& canvas) {
- canvas.drawRenderNode(receiverBackground.get());
- canvas.drawRenderNode(child.get());
- }, "A"); //A
-
- //prepareTree is required to find, which receivers have backward projected nodes
+ // Record time clip will be ignored by projectee
+ canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
+
+ canvas.translate(-SCROLL_X,
+ -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(projectingRipple.get());
+ },
+ "C"); // C
+ auto parent =
+ TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [&receiverBackground, &child](RenderProperties& properties,
+ SkiaRecordingCanvas& canvas) {
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ },
+ "A"); // A
+
+ // prepareTree is required to find, which receivers have backward projected nodes
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, parent.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -534,17 +631,16 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionChildScroll) {
}
namespace {
-static int drawNode(RenderThread& renderThread, const sp<RenderNode>& renderNode)
-{
+static int drawNode(RenderThread& renderThread, const sp<RenderNode>& renderNode) {
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, renderNode.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, renderNode.get(), &contextFactory));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
renderNode->prepareTree(info);
- //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+ // create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
ZReorderCanvas canvas(100, 100);
RenderNodeDrawable drawable(renderNode.get(), &canvas, false);
canvas.drawDrawable(&drawable);
@@ -560,18 +656,18 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedInMiddle) {
|
R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectionReceiver(true);
- } ); //nodeB
+ }); // nodeB
drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectBackwards(true);
props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
EXPECT_EQ(3, drawNode(renderThread, nodeA));
}
@@ -584,19 +680,21 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectLast) {
|
R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //drawn as 2
+ drawOrderedNode(&canvas, 3, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) { // drawn as 2
props.setProjectBackwards(true);
props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //drawn as 3
- props.setProjectionReceiver(true);
- } ); //nodeE
- }); //nodeA
+ }); // nodeR
+ }); // nodeC
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // drawn as 3
+ props.setProjectionReceiver(true);
+ }); // nodeE
+ }); // nodeA
EXPECT_EQ(4, drawNode(renderThread, nodeA));
}
@@ -608,17 +706,17 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderNoReceivable) {
|
R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- //not having a projection receiver is an undefined behavior
+ // not having a projection receiver is an undefined behavior
props.setProjectBackwards(true);
props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
EXPECT_EQ(2, drawNode(renderThread, nodeA));
}
@@ -630,17 +728,17 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderParentReceivable) {
|
R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectionReceiver(true);
drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectBackwards(true);
props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
EXPECT_EQ(3, drawNode(renderThread, nodeA));
}
@@ -652,22 +750,22 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderSameNodeReceivable) {
|
R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, nullptr); //nodeB
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, nullptr); // nodeB
drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- //having a node that is projected on itself is an undefined/unexpected behavior
+ // having a node that is projected on itself is an undefined/unexpected behavior
props.setProjectionReceiver(true);
props.setProjectBackwards(true);
props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
EXPECT_EQ(2, drawNode(renderThread, nodeA));
}
-//Note: the outcome for this test is different in HWUI
+// Note: the outcome for this test is different in HWUI
RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedSibling) {
/* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
A
@@ -675,18 +773,18 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedSibling) {
/ | \
B C R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- } ); //nodeC
+ }); // nodeB
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {}); // nodeC
drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectBackwards(true);
props.setClipToBounds(false);
- } ); //nodeR
- }); //nodeA
+ }); // nodeR
+ }); // nodeA
EXPECT_EQ(2, drawNode(renderThread, nodeA));
}
@@ -699,20 +797,20 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedSibling2) {
/ | \
B C R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- } ); //nodeC
+ }); // nodeB
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {}); // nodeC
drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectBackwards(true);
props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeG
- }); //nodeA
+ }); // nodeR
+ }); // nodeG
+ }); // nodeA
EXPECT_EQ(3, drawNode(renderThread, nodeA));
}
@@ -726,18 +824,19 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderGrandparentReceivable) {
|
R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setProjectionReceiver(true);
drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- } ); //nodeB
- }); //nodeA
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeB
+ }); // nodeA
EXPECT_EQ(3, drawNode(renderThread, nodeA));
}
@@ -749,21 +848,23 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivables) {
/ \
G R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // B
props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G
- props.setProjectionReceiver(true);
- } ); //nodeG
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
+ }); // nodeB
+ drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // C
+ drawOrderedNode(&canvas, 3,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // G
+ props.setProjectionReceiver(true);
+ }); // nodeG
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // R
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
EXPECT_EQ(4, drawNode(renderThread, nodeA));
}
@@ -775,21 +876,23 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivablesLikelyScena
/ \
G R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // B
props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G
- props.setProjectionReceiver(true);
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeG
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R
- } ); //nodeR
- } ); //nodeC
- }); //nodeA
+ }); // nodeB
+ drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // C
+ drawOrderedNode(&canvas, 1,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // G
+ props.setProjectionReceiver(true);
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeG
+ drawOrderedNode(&canvas, 3,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // R
+ }); // nodeR
+ }); // nodeC
+ }); // nodeA
EXPECT_EQ(4, drawNode(renderThread, nodeA));
}
@@ -803,23 +906,26 @@ RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivablesDeeper) {
|
R
*/
- auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B
+ auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) {
+ drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // B
props.setProjectionReceiver(true);
- } ); //nodeB
- drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C
- drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G
- props.setProjectionReceiver(true);
- } ); //nodeG
- drawOrderedNode(&canvas, 4, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //D
- drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R
- props.setProjectBackwards(true);
- props.setClipToBounds(false);
- } ); //nodeR
- } ); //nodeD
- } ); //nodeC
- }); //nodeA
+ }); // nodeB
+ drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // C
+ drawOrderedNode(&canvas, 2,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // G
+ props.setProjectionReceiver(true);
+ }); // nodeG
+ drawOrderedNode(&canvas, 4,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) { // D
+ drawOrderedNode(&canvas, 3, [](RenderProperties& props,
+ SkiaRecordingCanvas& canvas) { // R
+ props.setProjectBackwards(true);
+ props.setClipToBounds(false);
+ }); // nodeR
+ }); // nodeD
+ }); // nodeC
+ }); // nodeA
EXPECT_EQ(5, drawNode(renderThread, nodeA));
}
@@ -828,8 +934,7 @@ RENDERTHREAD_TEST(RenderNodeDrawable, simple) {
static const int CANVAS_HEIGHT = 200;
class SimpleTestCanvas : public TestCanvasBase {
public:
- SimpleTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {
- }
+ SimpleTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
EXPECT_EQ(0, mDrawCounter++);
}
@@ -839,11 +944,12 @@ RENDERTHREAD_TEST(RenderNodeDrawable, simple) {
};
auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25));
- canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
- canvas.drawBitmap(*bitmap, 10, 10, nullptr);
- });
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25));
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ SkPaint());
+ canvas.drawBitmap(*bitmap, 10, 10, nullptr);
+ });
SimpleTestCanvas canvas;
RenderNodeDrawable drawable(node.get(), &canvas, true);
@@ -856,33 +962,32 @@ RENDERTHREAD_TEST(RenderNodeDrawable, colorOp_unbounded) {
static const int CANVAS_HEIGHT = 200;
class ColorTestCanvas : public TestCanvasBase {
public:
- ColorTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {
- }
+ ColorTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {}
void onDrawPaint(const SkPaint&) {
switch (mDrawCounter++) {
- case 0:
- EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT),
- TestUtils::getClipBounds(this));
- break;
- case 1:
- EXPECT_EQ(SkRect::MakeWH(10, 10), TestUtils::getClipBounds(this));
- break;
- default:
- ADD_FAILURE();
+ case 0:
+ EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT),
+ TestUtils::getClipBounds(this));
+ break;
+ case 1:
+ EXPECT_EQ(SkRect::MakeWH(10, 10), TestUtils::getClipBounds(this));
+ break;
+ default:
+ ADD_FAILURE();
}
}
};
- auto unclippedColorView = TestUtils::createSkiaNode(0, 0, 10, 10,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- props.setClipToBounds(false);
- canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
- });
+ auto unclippedColorView = TestUtils::createSkiaNode(
+ 0, 0, 10, 10, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ props.setClipToBounds(false);
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
- auto clippedColorView = TestUtils::createSkiaNode(0, 0, 10, 10,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
- });
+ auto clippedColorView = TestUtils::createSkiaNode(
+ 0, 0, 10, 10, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
ColorTestCanvas canvas;
RenderNodeDrawable drawable(unclippedColorView.get(), &canvas, true);
@@ -898,42 +1003,43 @@ TEST(RenderNodeDrawable, renderNode) {
static const int CANVAS_HEIGHT = 200;
class RenderNodeTestCanvas : public TestCanvasBase {
public:
- RenderNodeTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {
- }
+ RenderNodeTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
- switch(mDrawCounter++) {
- case 0:
- EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this));
- EXPECT_EQ(SK_ColorDKGRAY, paint.getColor());
- break;
- case 1:
- EXPECT_EQ(SkRect::MakeLTRB(50, 50, 150, 150), TestUtils::getClipBounds(this));
- EXPECT_EQ(SK_ColorWHITE, paint.getColor());
- break;
- default:
- ADD_FAILURE();
+ switch (mDrawCounter++) {
+ case 0:
+ EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT),
+ TestUtils::getClipBounds(this));
+ EXPECT_EQ(SK_ColorDKGRAY, paint.getColor());
+ break;
+ case 1:
+ EXPECT_EQ(SkRect::MakeLTRB(50, 50, 150, 150), TestUtils::getClipBounds(this));
+ EXPECT_EQ(SK_ColorWHITE, paint.getColor());
+ break;
+ default:
+ ADD_FAILURE();
}
}
};
- auto child = TestUtils::createSkiaNode(10, 10, 110, 110,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, 100, 100, paint);
- });
+ auto child = TestUtils::createSkiaNode(
+ 10, 10, 110, 110, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
- auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ auto parent = TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[&child](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorDKGRAY);
- canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint);
-
- canvas.save(SaveFlags::MatrixClip);
- canvas.translate(40, 40);
- canvas.drawRenderNode(child.get());
- canvas.restore();
- });
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint);
+
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.translate(40, 40);
+ canvas.drawRenderNode(child.get());
+ canvas.restore();
+ });
RenderNodeTestCanvas canvas;
RenderNodeDrawable drawable(parent.get(), &canvas, true);
@@ -941,6 +1047,39 @@ TEST(RenderNodeDrawable, renderNode) {
EXPECT_EQ(2, canvas.mDrawCounter);
}
+// Verify that layers are composed with kLow_SkFilterQuality filter quality.
+RENDERTHREAD_SKIA_PIPELINE_TEST(RenderNodeDrawable, layerComposeQuality) {
+ static const int CANVAS_WIDTH = 1;
+ static const int CANVAS_HEIGHT = 1;
+ static const int LAYER_WIDTH = 1;
+ static const int LAYER_HEIGHT = 1;
+ class FrameTestCanvas : public TestCanvasBase {
+ public:
+ FrameTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {}
+ void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+ const SkPaint* paint, SrcRectConstraint constraint) override {
+ mDrawCounter++;
+ EXPECT_EQ(kLow_SkFilterQuality, paint->getFilterQuality());
+ }
+ };
+
+ auto layerNode = TestUtils::createSkiaNode(
+ 0, 0, LAYER_WIDTH, LAYER_HEIGHT,
+ [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+ canvas.drawPaint(SkPaint());
+ });
+
+ layerNode->animatorProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+ layerNode->setLayerSurface(SkSurface::MakeRasterN32Premul(LAYER_WIDTH, LAYER_HEIGHT));
+
+ FrameTestCanvas canvas;
+ RenderNodeDrawable drawable(layerNode.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(1, canvas.mDrawCounter); //make sure the layer was composed
+
+ // clean up layer pointer, so we can safely destruct RenderNode
+ layerNode->setLayerSurface(nullptr);
+}
TEST(ReorderBarrierDrawable, testShadowMatrix) {
static const int CANVAS_WIDTH = 100;
@@ -952,7 +1091,6 @@ TEST(ReorderBarrierDrawable, testShadowMatrix) {
static const float CASTER_WIDTH = 20.0f;
static const float CASTER_HEIGHT = 20.0f;
-
class ShadowTestCanvas : public SkCanvas {
public:
ShadowTestCanvas(int width, int height) : SkCanvas(width, height) {}
@@ -976,32 +1114,77 @@ TEST(ReorderBarrierDrawable, testShadowMatrix) {
// matrix.
mDrawCounter++;
EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X, CASTER_Y), matrix);
- EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X+TRANSLATE_X, CASTER_Y+TRANSLATE_Y),
- getTotalMatrix());
+ EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y),
+ getTotalMatrix());
}
+
protected:
int mDrawCounter = 0;
};
- auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ auto parent = TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.translate(TRANSLATE_X, TRANSLATE_Y);
- canvas.insertReorderBarrier(true);
-
- auto node = TestUtils::createSkiaNode(CASTER_X, CASTER_Y, CASTER_X + CASTER_WIDTH,
- CASTER_Y + CASTER_HEIGHT,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- props.setElevation(42);
- props.mutableOutline().setRoundRect(0, 0, 20, 20, 5, 1);
- props.mutableOutline().setShouldClip(true);
- });
- canvas.drawRenderNode(node.get());
- canvas.insertReorderBarrier(false);
- });
+ canvas.translate(TRANSLATE_X, TRANSLATE_Y);
+ canvas.insertReorderBarrier(true);
+
+ auto node = TestUtils::createSkiaNode(
+ CASTER_X, CASTER_Y, CASTER_X + CASTER_WIDTH, CASTER_Y + CASTER_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ props.setElevation(42);
+ props.mutableOutline().setRoundRect(0, 0, 20, 20, 5, 1);
+ props.mutableOutline().setShouldClip(true);
+ });
+ canvas.drawRenderNode(node.get());
+ canvas.insertReorderBarrier(false);
+ });
- //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+ // create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
ShadowTestCanvas canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
RenderNodeDrawable drawable(parent.get(), &canvas, false);
canvas.drawDrawable(&drawable);
EXPECT_EQ(6, canvas.getIndex());
-} \ No newline at end of file
+}
+
+// Draw a vector drawable twice but with different bounds and verify correct bounds are used.
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaRecordingCanvas, drawVectorDrawable) {
+ static const int CANVAS_WIDTH = 100;
+ static const int CANVAS_HEIGHT = 200;
+ class VectorDrawableTestCanvas : public TestCanvasBase {
+ public:
+ VectorDrawableTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {}
+ void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
+ const SkPaint* paint, SrcRectConstraint constraint) override {
+ const int index = mDrawCounter++;
+ switch (index) {
+ case 0:
+ EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT));
+ break;
+ case 1:
+ EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH/2, CANVAS_HEIGHT));
+ break;
+ default:
+ ADD_FAILURE();
+ }
+ }
+ };
+
+ VectorDrawable::Group* group = new VectorDrawable::Group();
+ sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
+ vectorDrawable->mutateStagingProperties()->setScaledSize(CANVAS_WIDTH/10, CANVAS_HEIGHT/10);
+
+ auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [&](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH,
+ CANVAS_HEIGHT));
+ canvas.drawVectorDrawable(vectorDrawable.get());
+ vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH/2,
+ CANVAS_HEIGHT));
+ canvas.drawVectorDrawable(vectorDrawable.get());
+ });
+
+ VectorDrawableTestCanvas canvas;
+ RenderNodeDrawable drawable(node.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(2, canvas.mDrawCounter);
+}
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index eda4a9de49ae..079520836bb5 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
#include <VectorDrawable.h>
+#include <gtest/gtest.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
@@ -32,21 +32,20 @@ using namespace android::uirenderer::renderthread;
class ContextFactory : public android::uirenderer::IContextFactory {
public:
- android::uirenderer::AnimationContext* createAnimationContext
- (android::uirenderer::renderthread::TimeLord& clock) override {
+ android::uirenderer::AnimationContext* createAnimationContext(
+ android::uirenderer::renderthread::TimeLord& clock) override {
return new android::uirenderer::AnimationContext(clock);
}
};
TEST(RenderNode, hasParents) {
- auto child = TestUtils::createNode(0, 0, 200, 400,
- [](RenderProperties& props, Canvas& canvas) {
+ auto child = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
});
auto parent = TestUtils::createNode(0, 0, 200, 400,
- [&child](RenderProperties& props, Canvas& canvas) {
- canvas.drawRenderNode(child.get());
- });
+ [&child](RenderProperties& props, Canvas& canvas) {
+ canvas.drawRenderNode(child.get());
+ });
TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
@@ -67,14 +66,13 @@ TEST(RenderNode, hasParents) {
}
TEST(RenderNode, validity) {
- auto child = TestUtils::createNode(0, 0, 200, 400,
- [](RenderProperties& props, Canvas& canvas) {
+ auto child = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
});
auto parent = TestUtils::createNode(0, 0, 200, 400,
- [&child](RenderProperties& props, Canvas& canvas) {
- canvas.drawRenderNode(child.get());
- });
+ [&child](RenderProperties& props, Canvas& canvas) {
+ canvas.drawRenderNode(child.get());
+ });
EXPECT_TRUE(child->isValid());
EXPECT_TRUE(parent->isValid());
@@ -111,9 +109,8 @@ TEST(RenderNode, validity) {
EXPECT_TRUE(child->isValid());
EXPECT_TRUE(child->nothingToDraw());
- TestUtils::recordNode(*parent, [&child](Canvas& canvas) {
- canvas.drawRenderNode(child.get());
- });
+ TestUtils::recordNode(*parent,
+ [&child](Canvas& canvas) { canvas.drawRenderNode(child.get()); });
TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
@@ -131,18 +128,17 @@ TEST(RenderNode, validity) {
}
TEST(RenderNode, multiTreeValidity) {
- auto child = TestUtils::createNode(0, 0, 200, 400,
- [](RenderProperties& props, Canvas& canvas) {
+ auto child = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
});
auto parent1 = TestUtils::createNode(0, 0, 200, 400,
- [&child](RenderProperties& props, Canvas& canvas) {
- canvas.drawRenderNode(child.get());
- });
+ [&child](RenderProperties& props, Canvas& canvas) {
+ canvas.drawRenderNode(child.get());
+ });
auto parent2 = TestUtils::createNode(0, 0, 200, 400,
- [&child](RenderProperties& props, Canvas& canvas) {
- canvas.drawRenderNode(child.get());
- });
+ [&child](RenderProperties& props, Canvas& canvas) {
+ canvas.drawRenderNode(child.get());
+ });
EXPECT_TRUE(child->isValid());
EXPECT_TRUE(parent1->isValid());
@@ -200,14 +196,12 @@ TEST(RenderNode, multiTreeValidity) {
});
TestUtils::syncHierarchyPropertiesAndDisplayList(child);
- TestUtils::recordNode(*parent1, [&child](Canvas& canvas) {
- canvas.drawRenderNode(child.get());
- });
+ TestUtils::recordNode(*parent1,
+ [&child](Canvas& canvas) { canvas.drawRenderNode(child.get()); });
TestUtils::syncHierarchyPropertiesAndDisplayList(parent1);
- TestUtils::recordNode(*parent2, [&child](Canvas& canvas) {
- canvas.drawRenderNode(child.get());
- });
+ TestUtils::recordNode(*parent2,
+ [&child](Canvas& canvas) { canvas.drawRenderNode(child.get()); });
TestUtils::syncHierarchyPropertiesAndDisplayList(parent2);
EXPECT_TRUE(child->isValid());
@@ -240,9 +234,8 @@ TEST(RenderNode, releasedCallback) {
class DecRefOnReleased : public GlFunctorLifecycleListener {
public:
explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
- void onGlFunctorReleased(Functor* functor) override {
- *mRefCnt -= 1;
- }
+ void onGlFunctorReleased(Functor* functor) override { *mRefCnt -= 1; }
+
private:
int* mRefCnt;
};
@@ -251,8 +244,7 @@ TEST(RenderNode, releasedCallback) {
sp<DecRefOnReleased> listener(new DecRefOnReleased(&refcnt));
Functor noopFunctor;
- auto node = TestUtils::createNode(0, 0, 200, 400,
- [&](RenderProperties& props, Canvas& canvas) {
+ auto node = TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
refcnt++;
canvas.callDrawGLFunction(&noopFunctor, listener.get());
});
@@ -277,17 +269,17 @@ TEST(RenderNode, releasedCallback) {
RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, rootNode.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
{
- auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400,
- [](RenderProperties& props, Canvas& canvas) {
- canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
- });
+ auto nonNullDLNode =
+ TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
+ });
TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
EXPECT_TRUE(nonNullDLNode->getDisplayList());
nonNullDLNode->prepareTree(info);
@@ -304,17 +296,16 @@ RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
}
RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
-
VectorDrawable::Group* group = new VectorDrawable::Group();
sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
- auto rootNode = TestUtils::createNode(0, 0, 200, 400,
- [&](RenderProperties& props, Canvas& canvas) {
- canvas.drawVectorDrawable(vectorDrawable.get());
- });
+ auto rootNode =
+ TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
+ canvas.drawVectorDrawable(vectorDrawable.get());
+ });
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, rootNode.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
LayerUpdateQueue layerUpdateQueue;
diff --git a/libs/hwui/tests/unit/ShaderCacheTests.cpp b/libs/hwui/tests/unit/ShaderCacheTests.cpp
new file mode 100644
index 000000000000..43080a9460b3
--- /dev/null
+++ b/libs/hwui/tests/unit/ShaderCacheTests.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <dirent.h>
+#include <cutils/properties.h>
+#include <cstdint>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <utils/Log.h>
+#include "pipeline/skia/ShaderCache.h"
+#include "FileBlobCache.h"
+
+using namespace android::uirenderer::skiapipeline;
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class ShaderCacheTestUtils {
+public:
+ /**
+ * "setSaveDelay" sets the time in seconds to wait before saving newly inserted cache entries.
+ * If set to 0, then deferred save is disabled.
+ */
+ static void setSaveDelay(ShaderCache& cache, unsigned int saveDelay) {
+ cache.mDeferredSaveDelay = saveDelay;
+ }
+
+ /**
+ * "terminate" optionally stores the BlobCache on disk and release all in-memory cache.
+ * Next call to "initShaderDiskCache" will load again the in-memory cache from disk.
+ */
+ static void terminate(ShaderCache& cache, bool saveContent) {
+ std::lock_guard<std::mutex> lock(cache.mMutex);
+ if (cache.mInitialized && cache.mBlobCache && saveContent) {
+ cache.mBlobCache->writeToFile();
+ }
+ cache.mBlobCache = NULL;
+ }
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
+
+
+namespace {
+
+std::string getExternalStorageFolder() {
+ return getenv("EXTERNAL_STORAGE");
+}
+
+bool folderExist(const std::string& folderName) {
+ DIR* dir = opendir(folderName.c_str());
+ if (dir) {
+ closedir(dir);
+ return true;
+ }
+ return false;
+}
+
+bool checkShader(const sk_sp<SkData>& shader, const char* program) {
+ sk_sp<SkData> shader2 = SkData::MakeWithCString(program);
+ return shader->size() == shader2->size()
+ && 0 == memcmp(shader->data(), shader2->data(), shader->size());
+}
+
+bool checkShader(const sk_sp<SkData>& shader, std::vector<char>& program) {
+ sk_sp<SkData> shader2 = SkData::MakeWithCopy(program.data(), program.size());
+ return shader->size() == shader2->size()
+ && 0 == memcmp(shader->data(), shader2->data(), shader->size());
+}
+
+void setShader(sk_sp<SkData>& shader, const char* program) {
+ shader = SkData::MakeWithCString(program);
+}
+
+void setShader(sk_sp<SkData>& shader, std::vector<char>& program) {
+ shader = SkData::MakeWithCopy(program.data(), program.size());
+}
+
+
+
+#define GrProgramDescTest(a) (*SkData::MakeWithCString(#a).get())
+
+TEST(ShaderCacheTest, testWriteAndRead) {
+ if (!folderExist(getExternalStorageFolder())) {
+ //don't run the test if external storage folder is not available
+ return;
+ }
+ std::string cacheFile1 = getExternalStorageFolder() + "/shaderCacheTest1";
+ std::string cacheFile2 = getExternalStorageFolder() + "/shaderCacheTest2";
+
+ //remove any test files from previous test run
+ int deleteFile = remove(cacheFile1.c_str());
+ ASSERT_TRUE(0 == deleteFile || ENOENT == errno);
+
+ //read the cache from a file that does not exist
+ ShaderCache::get().setFilename(cacheFile1.c_str());
+ ShaderCacheTestUtils::setSaveDelay(ShaderCache::get(), 0); //disable deferred save
+ ShaderCache::get().initShaderDiskCache();
+
+ //read a key - should not be found since the cache is empty
+ sk_sp<SkData> outVS;
+ ASSERT_EQ(ShaderCache::get().load(GrProgramDescTest(432)), sk_sp<SkData>());
+
+ //write to the in-memory cache without storing on disk and verify we read the same values
+ sk_sp<SkData> inVS;
+ setShader(inVS, "sassas");
+ ShaderCache::get().store(GrProgramDescTest(100), *inVS.get());
+ setShader(inVS, "someVS");
+ ShaderCache::get().store(GrProgramDescTest(432), *inVS.get());
+ ASSERT_NE((outVS = ShaderCache::get().load(GrProgramDescTest(100))), sk_sp<SkData>());
+ ASSERT_TRUE(checkShader(outVS, "sassas"));
+ ASSERT_NE((outVS = ShaderCache::get().load(GrProgramDescTest(432))), sk_sp<SkData>());
+ ASSERT_TRUE(checkShader(outVS, "someVS"));
+
+ //store content to disk and release in-memory cache
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), true);
+
+ //change to a file that does not exist and verify load fails
+ ShaderCache::get().setFilename(cacheFile2.c_str());
+ ShaderCache::get().initShaderDiskCache();
+ ASSERT_EQ(ShaderCache::get().load(GrProgramDescTest(432)), sk_sp<SkData>());
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), false);
+
+ //load again content from disk from an existing file and check the data is read correctly
+ ShaderCache::get().setFilename(cacheFile1.c_str());
+ ShaderCache::get().initShaderDiskCache();
+ sk_sp<SkData> outVS2;
+ ASSERT_NE((outVS2 = ShaderCache::get().load(GrProgramDescTest(432))), sk_sp<SkData>());
+ ASSERT_TRUE(checkShader(outVS2, "someVS"));
+
+ //change data, store to disk, read back again and verify data has been changed
+ setShader(inVS, "ewData1");
+ ShaderCache::get().store(GrProgramDescTest(432), *inVS.get());
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), true);
+ ShaderCache::get().initShaderDiskCache();
+ ASSERT_NE((outVS2 = ShaderCache::get().load(GrProgramDescTest(432))), sk_sp<SkData>());
+ ASSERT_TRUE(checkShader(outVS2, "ewData1"));
+
+
+ //write and read big data chunk (50K)
+ size_t dataSize = 50*1024;
+ std::vector<char> dataBuffer(dataSize);
+ for (size_t i = 0; i < dataSize; i++) {
+ dataBuffer[0] = dataSize % 256;
+ }
+ setShader(inVS, dataBuffer);
+ ShaderCache::get().store(GrProgramDescTest(432), *inVS.get());
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), true);
+ ShaderCache::get().initShaderDiskCache();
+ ASSERT_NE((outVS2 = ShaderCache::get().load(GrProgramDescTest(432))), sk_sp<SkData>());
+ ASSERT_TRUE(checkShader(outVS2, dataBuffer));
+
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), false);
+ remove(cacheFile1.c_str());
+}
+
+} // namespace
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
index 85b12ba79a8c..bc742b0c5a63 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -16,13 +16,13 @@
#include "tests/common/TestUtils.h"
-#include <gtest/gtest.h>
#include <SkBlurDrawLooper.h>
#include <SkColorMatrixFilter.h>
#include <SkColorSpace.h>
#include <SkImagePriv.h>
#include <SkPathOps.h>
#include <SkShader.h>
+#include <gtest/gtest.h>
using namespace android;
using namespace android::uirenderer;
@@ -42,15 +42,13 @@ SkBitmap createSkBitmap(int width, int height) {
TEST(SkiaBehavior, CreateBitmapShader1x1) {
SkBitmap origBitmap = createSkBitmap(1, 1);
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(origBitmap, kNever_SkCopyPixelsMode);
- sk_sp<SkShader> s = image->makeShader(
- SkShader::kClamp_TileMode,
- SkShader::kRepeat_TileMode,
- nullptr);
+ sk_sp<SkShader> s =
+ image->makeShader(SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, nullptr);
SkBitmap bitmap;
SkShader::TileMode xy[2];
ASSERT_TRUE(s->isABitmap(&bitmap, nullptr, xy))
- << "1x1 bitmap shader must query as bitmap shader";
+ << "1x1 bitmap shader must query as bitmap shader";
EXPECT_EQ(origBitmap.pixelRef(), bitmap.pixelRef());
}
@@ -63,8 +61,7 @@ TEST(SkiaBehavior, genIds) {
TEST(SkiaBehavior, lightingColorFilter_simplify) {
{
- sk_sp<SkColorFilter> filter(
- SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0));
+ sk_sp<SkColorFilter> filter(SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0));
SkColor observedColor;
SkBlendMode observedMode;
@@ -74,8 +71,7 @@ TEST(SkiaBehavior, lightingColorFilter_simplify) {
}
{
- sk_sp<SkColorFilter> failFilter(
- SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0x1));
+ sk_sp<SkColorFilter> failFilter(SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0x1));
EXPECT_FALSE(failFilter->asColorMode(nullptr, nullptr));
}
}
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index c048dda4a2e9..1d7dc3d06ee4 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -16,12 +16,12 @@
#include "tests/common/TestUtils.h"
-#include <gtest/gtest.h>
#include <RecordingCanvas.h>
#include <SkBlurDrawLooper.h>
#include <SkCanvasStateUtils.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>
+#include <gtest/gtest.h>
using namespace android;
using namespace android::uirenderer;
@@ -36,7 +36,6 @@ OPENGL_PIPELINE_TEST(SkiaCanvasProxy, drawGlyphsViaPicture) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
static const char* text = "testing text bounds";
// draw text directly into Recording canvas
@@ -45,8 +44,7 @@ OPENGL_PIPELINE_TEST(SkiaCanvasProxy, drawGlyphsViaPicture) {
// record the same text draw into a SkPicture and replay it into a Recording canvas
SkPictureRecorder recorder;
SkCanvas* skCanvas = recorder.beginRecording(200, 200, NULL, 0);
- std::unique_ptr<Canvas> pictCanvas(Canvas::create_canvas(skCanvas,
- Canvas::XformToSRGB::kDefer));
+ std::unique_ptr<Canvas> pictCanvas(Canvas::create_canvas(skCanvas));
TestUtils::drawUtf8ToCanvas(pictCanvas.get(), text, paint, 25, 25);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
@@ -65,7 +63,7 @@ OPENGL_PIPELINE_TEST(SkiaCanvasProxy, drawGlyphsViaPicture) {
TEST(SkiaCanvas, drawShadowLayer) {
auto surface = SkSurface::MakeRasterN32Premul(10, 10);
- SkiaCanvas canvas(surface->getCanvas(), Canvas::XformToSRGB::kDefer);
+ SkiaCanvas canvas(surface->getCanvas());
// clear to white
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrc);
@@ -89,7 +87,7 @@ TEST(SkiaCanvas, colorSpaceXform) {
sk_sp<Bitmap> adobeBitmap = Bitmap::allocateHeapBitmap(adobeInfo);
SkBitmap adobeSkBitmap;
adobeBitmap->getSkBitmap(&adobeSkBitmap);
- *adobeSkBitmap.getAddr32(0, 0) = 0xFF0000F0; // Opaque, almost fully-red
+ *adobeSkBitmap.getAddr32(0, 0) = 0xFF0000F0; // Opaque, almost fully-red
SkImageInfo info = adobeInfo.makeColorSpace(nullptr);
sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
@@ -108,27 +106,14 @@ TEST(SkiaCanvas, colorSpaceXform) {
// The result should be less than fully red, since we convert to Adobe RGB at draw time.
ASSERT_EQ(0xFF0000DC, *adobeSkBitmap.getAddr32(0, 0));
- // Now try in kDefer mode. This is a little strange given that, in practice, all software
- // canvases are kImmediate.
- SkCanvas skCanvas(skBitmap);
- SkiaCanvas deferCanvas(&skCanvas, Canvas::XformToSRGB::kDefer);
- deferCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
- // The result should be as before, since we deferred the conversion to sRGB.
- ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
-
- // Test picture recording. We will kDefer the xform at recording time, but handle it when
- // we playback to the software canvas.
+ // Test picture recording.
SkPictureRecorder recorder;
SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
- SkiaCanvas picCanvas(skPicCanvas, Canvas::XformToSRGB::kDefer);
+ SkiaCanvas picCanvas(skPicCanvas);
picCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
- // Playback to a deferred canvas. The result should be as before.
- deferCanvas.asSkCanvas()->drawPicture(picture);
- ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
-
- // Playback to an immediate canvas. The result should be fully red.
+ // Playback to an software canvas. The result should be fully red.
canvas.asSkCanvas()->drawPicture(picture);
ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
}
@@ -155,7 +140,7 @@ TEST(SkiaCanvas, captureCanvasState) {
// Create a picture canvas.
SkPictureRecorder recorder;
SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
- SkiaCanvas picCanvas(skPicCanvas, Canvas::XformToSRGB::kDefer);
+ SkiaCanvas picCanvas(skPicCanvas);
state = picCanvas.captureCanvasState();
// Verify that we cannot get the CanvasState.
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index dd8f4b4ec8cc..88d6dcf990a5 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
#include <VectorDrawable.h>
+#include <gtest/gtest.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
@@ -79,7 +79,7 @@ TEST(SkiaDisplayList, reuseDisplayList) {
// detach the list that you just attempted to reuse
availableList = renderNode->detachAvailableList();
ASSERT_EQ(availableList.get(), &skiaDL);
- availableList.release(); // prevents an invalid free since our DL is stack allocated
+ availableList.release(); // prevents an invalid free since our DL is stack allocated
// after detaching there should return no available list
availableList = renderNode->detachAvailableList();
@@ -115,8 +115,8 @@ public:
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
ContextFactory contextFactory;
- std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
- renderThread, false, rootNode.get(), &contextFactory));
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -126,13 +126,13 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
// prepare with a clean VD
VectorDrawableRoot cleanVD(new VectorDrawable::Group());
skiaDL.mVectorDrawables.push_back(&cleanVD);
- cleanVD.getBitmapUpdateIfDirty(); // this clears the dirty bit
+ cleanVD.getBitmapUpdateIfDirty(); // this clears the dirty bit
ASSERT_FALSE(cleanVD.isDirty());
ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
TestUtils::MockTreeObserver observer;
ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
- [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
// prepare again this time adding a dirty VD
@@ -142,7 +142,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
ASSERT_TRUE(dirtyVD.isDirty());
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
ASSERT_TRUE(skiaDL.prepareListAndChildren(observer, info, false,
- [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
// prepare again this time adding a RenderNode and a callback
@@ -151,13 +151,15 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
SkCanvas dummyCanvas;
skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
bool hasRun = false;
- ASSERT_TRUE(skiaDL.prepareListAndChildren(observer, info, false,
- [&hasRun, renderNode, infoPtr](RenderNode* n, TreeObserver& observer, TreeInfo& i, bool r) {
- hasRun = true;
- ASSERT_EQ(renderNode.get(), n);
- ASSERT_EQ(infoPtr, &i);
- ASSERT_FALSE(r);
- }));
+ ASSERT_TRUE(skiaDL.prepareListAndChildren(
+ observer, info, false,
+ [&hasRun, renderNode, infoPtr](RenderNode* n, TreeObserver& observer, TreeInfo& i,
+ bool r) {
+ hasRun = true;
+ ASSERT_EQ(renderNode.get(), n);
+ ASSERT_EQ(infoPtr, &i);
+ ASSERT_FALSE(r);
+ }));
ASSERT_TRUE(hasRun);
canvasContext->destroy();
@@ -169,7 +171,5 @@ TEST(SkiaDisplayList, updateChildren) {
sp<RenderNode> renderNode = new RenderNode();
SkCanvas dummyCanvas;
skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
- skiaDL.updateChildren([renderNode](RenderNode* n) {
- ASSERT_EQ(renderNode.get(), n);
- });
+ skiaDL.updateChildren([renderNode](RenderNode* n) { ASSERT_EQ(renderNode.get(), n); });
}
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index b397b151ad76..42a92fcc7d89 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -14,22 +14,22 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
#include <VectorDrawable.h>
+#include <gtest/gtest.h>
+#include <SkClipStack.h>
+#include <SkLiteRecorder.h>
+#include <SkSurface_Base.h>
+#include <string.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
#include "IContextFactory.h"
+#include "SkiaCanvas.h"
#include "pipeline/skia/SkiaDisplayList.h"
-#include "pipeline/skia/SkiaRecordingCanvas.h"
#include "pipeline/skia/SkiaOpenGLPipeline.h"
+#include "pipeline/skia/SkiaRecordingCanvas.h"
#include "renderthread/CanvasContext.h"
#include "tests/common/TestUtils.h"
-#include "SkiaCanvas.h"
-#include <SkClipStack.h>
-#include <SkLiteRecorder.h>
-#include <SkSurface_Base.h>
-#include <string.h>
using namespace android;
using namespace android::uirenderer;
@@ -37,10 +37,31 @@ using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::skiapipeline;
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrame) {
- auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
- [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
- redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
- });
+ auto redNode = TestUtils::createSkiaNode(
+ 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+ redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+ });
+ LayerUpdateQueue layerUpdateQueue;
+ SkRect dirty = SkRect::MakeLargest();
+ std::vector<sp<RenderNode>> renderNodes;
+ renderNodes.push_back(redNode);
+ bool opaque = true;
+ android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
+ auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+ surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+ ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
+ ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
+}
+
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, testOnPrepareTree) {
+ auto redNode = TestUtils::createSkiaNode(
+ 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+ redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+ });
+
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeLargest();
std::vector<sp<RenderNode>> renderNodes;
@@ -48,22 +69,34 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrame) {
bool opaque = true;
android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ {
+ // add a pointer to a deleted vector drawable object in the pipeline
+ sp<VectorDrawableRoot> dirtyVD(new VectorDrawableRoot(new VectorDrawable::Group()));
+ dirtyVD->mutateProperties()->setScaledSize(5, 5);
+ pipeline->getVectorDrawables()->push_back(dirtyVD.get());
+ }
+
+ // pipeline should clean list of dirty vector drawables before prepare tree
+ pipeline->onPrepareTree();
+
auto surface = SkSurface::MakeRasterN32Premul(1, 1);
surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes,
- opaque, false, contentDrawBounds, surface);
+
+ // drawFrame will crash if "SkiaPipeline::onPrepareTree" did not clean invalid VD pointer
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
}
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) {
- auto halfGreenNode = TestUtils::createSkiaNode(0, 0, 2, 2,
- [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
- SkPaint greenPaint;
- greenPaint.setColor(SK_ColorGREEN);
- greenPaint.setStyle(SkPaint::kFill_Style);
- bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint);
- });
+ auto halfGreenNode = TestUtils::createSkiaNode(
+ 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
+ SkPaint greenPaint;
+ greenPaint.setColor(SK_ColorGREEN);
+ greenPaint.setStyle(SkPaint::kFill_Style);
+ bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint);
+ });
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeLargest();
std::vector<sp<RenderNode>> renderNodes;
@@ -73,21 +106,21 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) {
auto surface = SkSurface::MakeRasterN32Premul(2, 2);
surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes,
- true, false, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds,
+ surface);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes,
- false, false, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, false, contentDrawBounds,
+ surface);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
}
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
- auto redNode = TestUtils::createSkiaNode(0, 0, 2, 2,
- [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
- redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
- });
+ auto redNode = TestUtils::createSkiaNode(
+ 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+ redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+ });
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeXYWH(0, 1, 2, 1);
std::vector<sp<RenderNode>> renderNodes;
@@ -97,8 +130,8 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
auto surface = SkSurface::MakeRasterN32Premul(2, 2);
surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes,
- true, false, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds,
+ surface);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED);
@@ -106,27 +139,27 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
}
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderLayer) {
- auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
- [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
- redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
- });
+ auto redNode = TestUtils::createSkiaNode(
+ 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+ redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+ });
auto surfaceLayer1 = SkSurface::MakeRasterN32Premul(1, 1);
surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE);
redNode->setLayerSurface(surfaceLayer1);
- //create a 2nd 2x2 layer and add it to the queue as well.
- //make the layer's dirty area one half of the layer and verify only the dirty half is updated.
- auto blueNode = TestUtils::createSkiaNode(0, 0, 2, 2,
- [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
- blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
- });
+ // create a 2nd 2x2 layer and add it to the queue as well.
+ // make the layer's dirty area one half of the layer and verify only the dirty half is updated.
+ auto blueNode = TestUtils::createSkiaNode(
+ 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
+ blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+ });
auto surfaceLayer2 = SkSurface::MakeRasterN32Premul(2, 2);
surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE);
blueNode->setLayerSurface(surfaceLayer2);
- //attach both layers to the update queue
+ // attach both layers to the update queue
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeLargest();
layerUpdateQueue.enqueueLayerWithDamage(redNode.get(), dirty);
@@ -136,7 +169,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderLayer) {
bool opaque = true;
FrameBuilder::LightGeometry lightGeometry;
lightGeometry.radius = 1.0f;
- lightGeometry.center = { 0.0f, 0.0f, 0.0f };
+ lightGeometry.center = {0.0f, 0.0f, 0.0f};
BakedOpRenderer::LightInfo lightInfo;
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, false, lightInfo);
@@ -151,16 +184,16 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderLayer) {
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderOverdraw) {
ScopedProperty<bool> prop(Properties::debugOverdraw, true);
- auto whiteNode = TestUtils::createSkiaNode(0, 0, 1, 1,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
- });
+ auto whiteNode = TestUtils::createSkiaNode(
+ 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeXYWH(0, 0, 1, 1);
std::vector<sp<RenderNode>> renderNodes;
renderNodes.push_back(whiteNode);
bool opaque = true;
- //empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
+ // empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
auto surface = SkSurface::MakeRasterN32Premul(1, 1);
@@ -170,39 +203,39 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderOverdraw) {
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
// Single draw, should be white.
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque,
- false, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
// 1 Overdraw, should be blue blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque,
- false, contentDrawBounds, surface);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0d0ff);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
+ ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff);
// 2 Overdraw, should be green blended onto white
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque,
- false, contentDrawBounds, surface);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0ffd0);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
+ ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0);
// 3 Overdraw, should be pink blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque,
- false, contentDrawBounds, surface);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffffc0c0);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
+ ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0);
// 4 Overdraw, should be red blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque,
- false, contentDrawBounds, surface);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
+ ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
// 5 Overdraw, should be red blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque,
- false, contentDrawBounds, surface);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+ surface);
+ ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
}
namespace {
@@ -212,17 +245,12 @@ public:
DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
virtual ~DeferLayer() {}
- SkCanvas* onNewCanvas() override {
- return new T();
- }
- sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
- return nullptr;
- }
- sk_sp<SkImage> onNewImageSnapshot() override {
- return nullptr;
- }
+ SkCanvas* onNewCanvas() override { return new T(); }
+ sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
+ sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
T* canvas() { return static_cast<T*>(getCanvas()); }
void onCopyOnWrite(ContentChangeMode) override {}
+ void onWritePixels(const SkPixmap&, int x, int y) override {}
};
}
@@ -233,28 +261,28 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) {
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
SkMatrix expected;
switch (mDrawCounter++) {
- case 0:
- // background - left side
- EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
- expected.setTranslate(100, 100);
- break;
- case 1:
- // background - top side
- EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
- expected.setTranslate(100, 100);
- break;
- case 2:
- // content
- EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
- expected.setTranslate(-50, -50);
- break;
- case 3:
- // overlay
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
- expected.reset();
- break;
- default:
- ADD_FAILURE() << "Too many rects observed";
+ case 0:
+ // background - left side
+ EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
+ expected.setTranslate(100, 100);
+ break;
+ case 1:
+ // background - top side
+ EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
+ expected.setTranslate(100, 100);
+ break;
+ case 2:
+ // content
+ EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
+ expected.setTranslate(-50, -50);
+ break;
+ case 3:
+ // overlay
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
+ expected.reset();
+ break;
+ default:
+ ADD_FAILURE() << "Too many rects observed";
}
EXPECT_EQ(expected, getTotalMatrix());
}
@@ -266,23 +294,26 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) {
transparentPaint.setAlpha(128);
// backdrop
- nodes.push_back(TestUtils::createSkiaNode(100, 100, 700, 500, // 600x400
+ nodes.push_back(TestUtils::createSkiaNode(
+ 100, 100, 700, 500, // 600x400
[&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 600, 400, transparentPaint);
- }));
+ canvas.drawRect(0, 0, 600, 400, transparentPaint);
+ }));
// content
- android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300
- nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
+ android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300
+ nodes.push_back(TestUtils::createSkiaNode(
+ 0, 0, 800, 600,
[&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 800, 600, transparentPaint);
- }));
+ canvas.drawRect(0, 0, 800, 600, transparentPaint);
+ }));
// overlay
- nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
+ nodes.push_back(TestUtils::createSkiaNode(
+ 0, 0, 800, 600,
[&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.drawRect(0, 0, 800, 200, transparentPaint);
- }));
+ canvas.drawRect(0, 0, 800, 200, transparentPaint);
+ }));
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeWH(800, 600);
@@ -297,8 +328,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) {
static const int CANVAS_HEIGHT = 200;
class ClippedTestCanvas : public SkCanvas {
public:
- ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
- }
+ ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
EXPECT_EQ(0, mDrawCounter++);
EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this));
@@ -308,18 +338,19 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) {
};
std::vector<sp<RenderNode>> nodes;
- nodes.push_back(TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ nodes.push_back(TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
- canvas.drawBitmap(*bitmap, 0, 0, nullptr);
- }));
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ }));
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false,
- SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
+ SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
EXPECT_EQ(1, surface->canvas()->mDrawCounter);
}
@@ -328,8 +359,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
static const int CANVAS_HEIGHT = 50;
class ClipReplaceTestCanvas : public SkCanvas {
public:
- ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
- }
+ ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
void onDrawPaint(const SkPaint&) {
EXPECT_EQ(0, mDrawCounter++);
EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this))
@@ -339,17 +369,17 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
};
std::vector<sp<RenderNode>> nodes;
- nodes.push_back(TestUtils::createSkiaNode(20, 20, 30, 30,
- [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
- canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
- }));
+ nodes.push_back(TestUtils::createSkiaNode(
+ 20, 20, 30, 30, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ }));
LayerUpdateQueue layerUpdateQueue;
SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false,
- SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
+ SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
EXPECT_EQ(1, surface->canvas()->mDrawCounter);
}
diff --git a/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp
index 95c6ed6059b0..ad5fdacc8594 100644
--- a/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp
+++ b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp
@@ -14,23 +14,23 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
#include <VectorDrawable.h>
+#include <gtest/gtest.h>
+#include <SkClipStack.h>
+#include <SkLiteRecorder.h>
+#include <SkSurface_Base.h>
+#include <string.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
+#include "FatalTestCanvas.h"
#include "IContextFactory.h"
+#include "SkiaCanvas.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "pipeline/skia/SkiaPipeline.h"
#include "pipeline/skia/SkiaRecordingCanvas.h"
#include "renderthread/CanvasContext.h"
#include "tests/common/TestUtils.h"
-#include "SkiaCanvas.h"
-#include <SkSurface_Base.h>
-#include <SkLiteRecorder.h>
-#include <SkClipStack.h>
-#include "FatalTestCanvas.h"
-#include <string.h>
using namespace android;
using namespace android::uirenderer;
@@ -40,7 +40,7 @@ using namespace android::uirenderer::skiapipeline;
namespace {
static void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
- std::function<void(const SkCanvas&)> opValidateCallback) {
+ std::function<void(const SkCanvas&)> opValidateCallback) {
static const int CANVAS_WIDTH = 100;
static const int CANVAS_HEIGHT = 100;
class PropertyTestCanvas : public TestCanvasBase {
@@ -57,79 +57,88 @@ static void testProperty(std::function<void(RenderProperties&)> propSetupCallbac
std::function<void(const SkCanvas&)> mCallback;
};
- auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ auto node = TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[propSetupCallback](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- propSetupCallback(props);
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint);
- });
+ propSetupCallback(props);
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint);
+ });
PropertyTestCanvas canvas(opValidateCallback);
RenderNodeDrawable drawable(node.get(), &canvas, true);
canvas.drawDrawable(&drawable);
EXPECT_EQ(1, canvas.mDrawCounter);
}
-
}
TEST(RenderNodeDrawable, renderPropClipping) {
- testProperty([](RenderProperties& properties) {
- properties.setClipToBounds(true);
- properties.setClipBounds(android::uirenderer::Rect(10, 20, 300, 400));
- }, [](const SkCanvas& canvas) {
- EXPECT_EQ(SkRect::MakeLTRB(10, 20, 100, 100), TestUtils::getClipBounds(&canvas))
- << "Clip rect should be intersection of node bounds and clip bounds";
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.setClipToBounds(true);
+ properties.setClipBounds(android::uirenderer::Rect(10, 20, 300, 400));
+ },
+ [](const SkCanvas& canvas) {
+ EXPECT_EQ(SkRect::MakeLTRB(10, 20, 100, 100), TestUtils::getClipBounds(&canvas))
+ << "Clip rect should be intersection of node bounds and clip bounds";
+ });
}
TEST(RenderNodeDrawable, renderPropRevealClip) {
- testProperty([](RenderProperties& properties) {
- properties.mutableRevealClip().set(true, 50, 50, 25);
- }, [](const SkCanvas& canvas) {
- EXPECT_EQ(SkRect::MakeLTRB(25, 25, 75, 75), TestUtils::getClipBounds(&canvas));
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.mutableRevealClip().set(true, 50, 50, 25);
+ },
+ [](const SkCanvas& canvas) {
+ EXPECT_EQ(SkRect::MakeLTRB(25, 25, 75, 75), TestUtils::getClipBounds(&canvas));
+ });
}
TEST(RenderNodeDrawable, renderPropOutlineClip) {
- testProperty([](RenderProperties& properties) {
- properties.mutableOutline().setShouldClip(true);
- properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
- }, [](const SkCanvas& canvas) {
- EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(&canvas));
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.mutableOutline().setShouldClip(true);
+ properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
+ },
+ [](const SkCanvas& canvas) {
+ EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(&canvas));
+ });
}
TEST(RenderNodeDrawable, renderPropTransform) {
- testProperty([](RenderProperties& properties) {
- properties.setLeftTopRightBottom(10, 10, 110, 110);
-
- SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
- properties.setStaticMatrix(&staticMatrix);
-
- // ignored, since static overrides animation
- SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
- properties.setAnimationMatrix(&animationMatrix);
-
- properties.setTranslationX(10);
- properties.setTranslationY(20);
- properties.setScaleX(0.5f);
- properties.setScaleY(0.7f);
- }, [](const SkCanvas& canvas) {
- Matrix4 matrix;
- matrix.loadTranslate(10, 10, 0); // left, top
- matrix.scale(1.2f, 1.2f, 1); // static matrix
- // ignore animation matrix, since static overrides it
-
- // translation xy
- matrix.translate(10, 20);
-
- // scale xy (from default pivot - center)
- matrix.translate(50, 50);
- matrix.scale(0.5f, 0.7f, 1);
- matrix.translate(-50, -50);
- Matrix4 actual(canvas.getTotalMatrix());
- EXPECT_MATRIX_APPROX_EQ(matrix, actual)
- << "Op draw matrix must match expected combination of transformation properties";
- });
+ testProperty(
+ [](RenderProperties& properties) {
+ properties.setLeftTopRightBottom(10, 10, 110, 110);
+
+ SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
+ properties.setStaticMatrix(&staticMatrix);
+
+ // ignored, since static overrides animation
+ SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
+ properties.setAnimationMatrix(&animationMatrix);
+
+ properties.setTranslationX(10);
+ properties.setTranslationY(20);
+ properties.setScaleX(0.5f);
+ properties.setScaleY(0.7f);
+ },
+ [](const SkCanvas& canvas) {
+ Matrix4 matrix;
+ matrix.loadTranslate(10, 10, 0); // left, top
+ matrix.scale(1.2f, 1.2f, 1); // static matrix
+ // ignore animation matrix, since static overrides it
+
+ // translation xy
+ matrix.translate(10, 20);
+
+ // scale xy (from default pivot - center)
+ matrix.translate(50, 50);
+ matrix.scale(0.5f, 0.7f, 1);
+ matrix.translate(-50, -50);
+ Matrix4 actual(canvas.getTotalMatrix());
+ EXPECT_MATRIX_APPROX_EQ(matrix, actual) << "Op draw matrix must match expected "
+ "combination of transformation "
+ "properties";
+ });
}
diff --git a/libs/hwui/tests/unit/SnapshotTests.cpp b/libs/hwui/tests/unit/SnapshotTests.cpp
index 11797a8fc1db..9d673c82d4d0 100644
--- a/libs/hwui/tests/unit/SnapshotTests.cpp
+++ b/libs/hwui/tests/unit/SnapshotTests.cpp
@@ -32,16 +32,16 @@ TEST(Snapshot, serializeIntersectedClip) {
LinearAllocator allocator;
ClipRect rect(Rect(0, 0, 75, 75));
{
- auto intersectWithChild = child->serializeIntersectedClip(allocator,
- &rect, Matrix4::identity());
+ auto intersectWithChild =
+ child->serializeIntersectedClip(allocator, &rect, Matrix4::identity());
ASSERT_NE(nullptr, intersectWithChild);
EXPECT_EQ(Rect(50, 50, 75, 75), intersectWithChild->rect) << "Expect intersect with child";
}
rect.intersectWithRoot = true;
{
- auto intersectWithRoot = child->serializeIntersectedClip(allocator,
- &rect, Matrix4::identity());
+ auto intersectWithRoot =
+ child->serializeIntersectedClip(allocator, &rect, Matrix4::identity());
ASSERT_NE(nullptr, intersectWithRoot);
EXPECT_EQ(Rect(10, 10, 75, 75), intersectWithRoot->rect) << "Expect intersect with root";
}
diff --git a/libs/hwui/tests/unit/StringUtilsTests.cpp b/libs/hwui/tests/unit/StringUtilsTests.cpp
index b60e96c756ec..04fbb512e598 100644
--- a/libs/hwui/tests/unit/StringUtilsTests.cpp
+++ b/libs/hwui/tests/unit/StringUtilsTests.cpp
@@ -34,7 +34,7 @@ TEST(StringUtils, advancedBuildSet) {
auto collection = StringUtils::split("GL_ext1 GL_ext2 GL_ext3");
EXPECT_TRUE(collection.has("GL_ext1"));
- EXPECT_FALSE(collection.has("GL_ext")); // string present, but not in list
+ EXPECT_FALSE(collection.has("GL_ext")); // string present, but not in list
}
TEST(StringUtils, sizePrinter) {
diff --git a/libs/hwui/tests/unit/TestUtilsTests.cpp b/libs/hwui/tests/unit/TestUtilsTests.cpp
index 490595773724..742fe4210780 100644
--- a/libs/hwui/tests/unit/TestUtilsTests.cpp
+++ b/libs/hwui/tests/unit/TestUtilsTests.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "tests/common/TestUtils.h"
#include "Properties.h"
+#include "tests/common/TestUtils.h"
#include <gtest/gtest.h>
diff --git a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
index 8312bda8d67d..92d05e44c6ca 100644
--- a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
+++ b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
@@ -18,8 +18,8 @@
#include "GammaFontRenderer.h"
#include "TextDropShadowCache.h"
-#include "utils/Blur.h"
#include "tests/common/TestUtils.h"
+#include "utils/Blur.h"
#include <SkPaint.h>
@@ -29,6 +29,7 @@ using namespace android::uirenderer;
RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, addRemove) {
SkPaint paint;
paint.setTextSize(20);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
GammaFontRenderer gammaFontRenderer;
FontRenderer& fontRenderer = gammaFontRenderer.getFontRenderer();
@@ -40,15 +41,15 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, addRemove) {
std::vector<float> positions;
float totalAdvance;
uirenderer::Rect bounds;
- TestUtils::layoutTextUnscaled(paint, "This is a test",
- &glyphs, &positions, &totalAdvance, &bounds);
+ TestUtils::layoutTextUnscaled(paint, "This is a test", &glyphs, &positions, &totalAdvance,
+ &bounds);
EXPECT_TRUE(bounds.contains(5, -10, 100, 0)) << "Expect input to be nontrivially sized";
ShadowTexture* texture = cache.get(&paint, glyphs.data(), glyphs.size(), 10, positions.data());
ASSERT_TRUE(texture);
ASSERT_FALSE(texture->cleanup);
- ASSERT_EQ((uint32_t) texture->objectSize(), cache.getSize());
+ ASSERT_EQ((uint32_t)texture->objectSize(), cache.getSize());
ASSERT_TRUE(cache.getSize());
cache.clear();
ASSERT_EQ(cache.getSize(), 0u);
diff --git a/libs/hwui/tests/unit/ThreadBaseTests.cpp b/libs/hwui/tests/unit/ThreadBaseTests.cpp
new file mode 100644
index 000000000000..1168ff211202
--- /dev/null
+++ b/libs/hwui/tests/unit/ThreadBaseTests.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "thread/ThreadBase.h"
+#include "utils/TimeUtils.h"
+
+#include <chrono>
+#include "unistd.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+static ThreadBase& thread() {
+ class TestThread : public ThreadBase, public virtual RefBase {};
+ static sp<TestThread> thread = []() -> auto {
+ sp<TestThread> ret{new TestThread};
+ ret->start("TestThread");
+ return ret;
+ }
+ ();
+ return *thread;
+}
+
+static WorkQueue& queue() {
+ return thread().queue();
+}
+
+TEST(ThreadBase, post) {
+ std::atomic_bool ran(false);
+ queue().post([&ran]() { ran = true; });
+ for (int i = 0; !ran && i < 1000; i++) {
+ usleep(1);
+ }
+ ASSERT_TRUE(ran) << "Failed to flip atomic after 1 second";
+}
+
+TEST(ThreadBase, postDelay) {
+ using clock = WorkQueue::clock;
+
+ std::promise<nsecs_t> ranAtPromise;
+ auto queuedAt = clock::now();
+ queue().postDelayed(100_us, [&]() { ranAtPromise.set_value(clock::now()); });
+ auto ranAt = ranAtPromise.get_future().get();
+ auto ranAfter = ranAt - queuedAt;
+ ASSERT_TRUE(ranAfter > 90_us) << "Ran after " << ns2us(ranAfter) << "us <= 90us";
+}
+
+TEST(ThreadBase, runSync) {
+ pid_t thisTid = gettid();
+ pid_t otherTid = thisTid;
+
+ auto result = queue().runSync([&otherTid]() -> auto {
+ otherTid = gettid();
+ return 42;
+ });
+
+ ASSERT_EQ(42, result);
+ ASSERT_NE(thisTid, otherTid);
+}
+
+TEST(ThreadBase, async) {
+ pid_t thisTid = gettid();
+ pid_t thisPid = getpid();
+
+ auto otherTid = queue().async([]() -> auto { return gettid(); });
+ auto otherPid = queue().async([]() -> auto { return getpid(); });
+ auto result = queue().async([]() -> auto { return 42; });
+
+ ASSERT_NE(thisTid, otherTid.get());
+ ASSERT_EQ(thisPid, otherPid.get());
+ ASSERT_EQ(42, result.get());
+}
+
+TEST(ThreadBase, lifecyclePerf) {
+ struct EventCount {
+ std::atomic_int construct{0};
+ std::atomic_int destruct{0};
+ std::atomic_int copy{0};
+ std::atomic_int move{0};
+ };
+
+ struct Counter {
+ Counter(EventCount* count) : mCount(count) { mCount->construct++; }
+
+ Counter(const Counter& other) : mCount(other.mCount) {
+ if (mCount) mCount->copy++;
+ }
+
+ Counter(Counter&& other) : mCount(other.mCount) {
+ other.mCount = nullptr;
+ if (mCount) mCount->move++;
+ }
+
+ Counter& operator=(const Counter& other) {
+ mCount = other.mCount;
+ if (mCount) mCount->copy++;
+ return *this;
+ }
+
+ Counter& operator=(Counter&& other) {
+ mCount = other.mCount;
+ other.mCount = nullptr;
+ if (mCount) mCount->move++;
+ return *this;
+ }
+
+ ~Counter() {
+ if (mCount) mCount->destruct++;
+ }
+
+ EventCount* mCount;
+ };
+
+ EventCount count;
+ {
+ Counter counter{&count};
+ queue().runSync([c = std::move(counter)](){});
+ }
+ ASSERT_EQ(1, count.construct.load());
+ ASSERT_EQ(1, count.destruct.load());
+ ASSERT_EQ(0, count.copy.load());
+ ASSERT_LE(1, count.move.load());
+}
+
+int lifecycleTestHelper(const sp<VirtualLightRefBase>& test) {
+ return queue().runSync([t = test]()->int { return t->getStrongCount(); });
+}
+
+TEST(ThreadBase, lifecycle) {
+ sp<VirtualLightRefBase> dummyObject{new VirtualLightRefBase};
+ ASSERT_EQ(1, dummyObject->getStrongCount());
+ ASSERT_EQ(2, queue().runSync([dummyObject]() -> int { return dummyObject->getStrongCount(); }));
+ ASSERT_EQ(1, dummyObject->getStrongCount());
+ ASSERT_EQ(2, lifecycleTestHelper(dummyObject));
+ ASSERT_EQ(1, dummyObject->getStrongCount());
+} \ No newline at end of file
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index c90b6f0e9cdd..e424a266bf72 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -52,25 +52,26 @@ std::shared_ptr<minikin::FontFamily> buildFamily(const char* fileName) {
SkData::MakeWithProc(data, st.st_size, unmap, reinterpret_cast<void*>(st.st_size));
std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(skData));
sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
- sk_sp<SkTypeface> typeface(fm->createFromStream(fontData.release()));
+ sk_sp<SkTypeface> typeface(fm->makeFromStream(std::move(fontData)));
LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", fileName);
std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
- return std::make_shared<minikin::FontFamily>(
- std::vector<minikin::Font>({ minikin::Font(std::move(font), minikin::FontStyle()) }));
+ std::vector<minikin::Font> fonts;
+ fonts.push_back(minikin::Font::Builder(font).build());
+ return std::make_shared<minikin::FontFamily>(std::move(fonts));
}
std::vector<std::shared_ptr<minikin::FontFamily>> makeSingleFamlyVector(const char* fileName) {
- return std::vector<std::shared_ptr<minikin::FontFamily>>({ buildFamily(fileName) });
+ return std::vector<std::shared_ptr<minikin::FontFamily>>({buildFamily(fileName)});
}
TEST(TypefaceTest, resolveDefault_and_setDefaultTest) {
- std::unique_ptr<Typeface> regular(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoRegular),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ std::unique_ptr<Typeface> regular(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoRegular), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
EXPECT_EQ(regular.get(), Typeface::resolveDefault(regular.get()));
- Typeface* old = Typeface::resolveDefault(nullptr); // Keep the original to restore it later.
+ // Keep the original to restore it later.
+ const Typeface* old = Typeface::resolveDefault(nullptr);
ASSERT_NE(nullptr, old);
Typeface::setDefault(regular.get());
@@ -81,161 +82,176 @@ TEST(TypefaceTest, resolveDefault_and_setDefaultTest) {
TEST(TypefaceTest, createWithDifferentBaseWeight) {
std::unique_ptr<Typeface> bold(Typeface::createWithDifferentBaseWeight(nullptr, 700));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, bold->fSkiaStyle);
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, bold->fAPIStyle);
std::unique_ptr<Typeface> light(Typeface::createWithDifferentBaseWeight(nullptr, 300));
- EXPECT_EQ(3, light->fStyle.getWeight());
- EXPECT_FALSE(light->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, light->fSkiaStyle);
+ EXPECT_EQ(300, light->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, light->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, light->fAPIStyle);
}
TEST(TypefaceTest, createRelativeTest_fromRegular) {
// In Java, Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
- std::unique_ptr<Typeface> normal(Typeface::createRelative(nullptr, SkTypeface::kNormal));
- EXPECT_EQ(4, normal->fStyle.getWeight());
- EXPECT_FALSE(normal->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+ std::unique_ptr<Typeface> normal(Typeface::createRelative(nullptr, Typeface::kNormal));
+ EXPECT_EQ(400, normal->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, normal->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, normal->fAPIStyle);
// In Java, Typeface.create(Typeface.DEFAULT, Typeface.BOLD);
- std::unique_ptr<Typeface> bold(Typeface::createRelative(nullptr, SkTypeface::kBold));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+ std::unique_ptr<Typeface> bold(Typeface::createRelative(nullptr, Typeface::kBold));
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
// In Java, Typeface.create(Typeface.DEFAULT, Typeface.ITALIC);
- std::unique_ptr<Typeface> italic(Typeface::createRelative(nullptr, SkTypeface::kItalic));
- EXPECT_EQ(4, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ std::unique_ptr<Typeface> italic(Typeface::createRelative(nullptr, Typeface::kItalic));
+ EXPECT_EQ(400, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java, Typeface.create(Typeface.DEFAULT, Typeface.BOLD_ITALIC);
- std::unique_ptr<Typeface> boldItalic(
- Typeface::createRelative(nullptr, SkTypeface::kBoldItalic));
- EXPECT_EQ(7, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+ std::unique_ptr<Typeface> boldItalic(Typeface::createRelative(nullptr, Typeface::kBoldItalic));
+ EXPECT_EQ(700, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kBoldItalic, boldItalic->fAPIStyle);
}
TEST(TypefaceTest, createRelativeTest_BoldBase) {
std::unique_ptr<Typeface> base(Typeface::createWithDifferentBaseWeight(nullptr, 700));
- // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.NORMAL);
- std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
- EXPECT_EQ(7, normal->fStyle.getWeight());
- EXPECT_FALSE(normal->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.BOLD);
- std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
- EXPECT_EQ(10, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.ITALIC);
- std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
- EXPECT_EQ(7, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.BOLD_ITALIC);
- std::unique_ptr<Typeface>
- boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
- EXPECT_EQ(10, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+ // In Java, Typeface.create(Typeface.create("sans-serif-bold"),
+ // Typeface.NORMAL);
+ std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), Typeface::kNormal));
+ EXPECT_EQ(700, normal->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, normal->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, normal->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create("sans-serif-bold"),
+ // Typeface.BOLD);
+ std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), Typeface::kBold));
+ EXPECT_EQ(1000, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create("sans-serif-bold"),
+ // Typeface.ITALIC);
+ std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), Typeface::kItalic));
+ EXPECT_EQ(700, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create("sans-serif-bold"),
+ // Typeface.BOLD_ITALIC);
+ std::unique_ptr<Typeface> boldItalic(
+ Typeface::createRelative(base.get(), Typeface::kBoldItalic));
+ EXPECT_EQ(1000, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kBoldItalic, boldItalic->fAPIStyle);
}
TEST(TypefaceTest, createRelativeTest_LightBase) {
std::unique_ptr<Typeface> base(Typeface::createWithDifferentBaseWeight(nullptr, 300));
- // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.NORMAL);
- std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
- EXPECT_EQ(3, normal->fStyle.getWeight());
- EXPECT_FALSE(normal->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.BOLD);
- std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
- EXPECT_EQ(6, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.ITLIC);
- std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
- EXPECT_EQ(3, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.BOLD_ITALIC);
- std::unique_ptr<Typeface>
- boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
- EXPECT_EQ(6, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+ // In Java, Typeface.create(Typeface.create("sans-serif-light"),
+ // Typeface.NORMAL);
+ std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), Typeface::kNormal));
+ EXPECT_EQ(300, normal->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, normal->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, normal->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create("sans-serif-light"),
+ // Typeface.BOLD);
+ std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), Typeface::kBold));
+ EXPECT_EQ(600, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create("sans-serif-light"),
+ // Typeface.ITLIC);
+ std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), Typeface::kItalic));
+ EXPECT_EQ(300, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create("sans-serif-light"),
+ // Typeface.BOLD_ITALIC);
+ std::unique_ptr<Typeface> boldItalic(
+ Typeface::createRelative(base.get(), Typeface::kBoldItalic));
+ EXPECT_EQ(600, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kBoldItalic, boldItalic->fAPIStyle);
}
TEST(TypefaceTest, createRelativeTest_fromBoldStyled) {
- std::unique_ptr<Typeface> base(Typeface::createRelative(nullptr, SkTypeface::kBold));
-
- // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.NORMAL);
- std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
- EXPECT_EQ(4, normal->fStyle.getWeight());
- EXPECT_FALSE(normal->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
-
- // In Java Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.BOLD);
- std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.ITALIC);
- std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
- EXPECT_EQ(4, normal->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ std::unique_ptr<Typeface> base(Typeface::createRelative(nullptr, Typeface::kBold));
+
+ // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD),
+ // Typeface.NORMAL);
+ std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), Typeface::kNormal));
+ EXPECT_EQ(400, normal->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, normal->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, normal->fAPIStyle);
+
+ // In Java Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD),
+ // Typeface.BOLD);
+ std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), Typeface::kBold));
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD),
+ // Typeface.ITALIC);
+ std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), Typeface::kItalic));
+ EXPECT_EQ(400, normal->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java,
- // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.BOLD_ITALIC);
- std::unique_ptr<Typeface>
- boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
- EXPECT_EQ(7, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+ // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD),
+ // Typeface.BOLD_ITALIC);
+ std::unique_ptr<Typeface> boldItalic(
+ Typeface::createRelative(base.get(), Typeface::kBoldItalic));
+ EXPECT_EQ(700, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kBoldItalic, boldItalic->fAPIStyle);
}
TEST(TypefaceTest, createRelativeTest_fromItalicStyled) {
- std::unique_ptr<Typeface> base(Typeface::createRelative(nullptr, SkTypeface::kItalic));
+ std::unique_ptr<Typeface> base(Typeface::createRelative(nullptr, Typeface::kItalic));
// In Java,
- // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.NORMAL);
- std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
- EXPECT_EQ(4, normal->fStyle.getWeight());
- EXPECT_FALSE(normal->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
-
- // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.BOLD);
- std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+ // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC),
+ // Typeface.NORMAL);
+ std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), Typeface::kNormal));
+ EXPECT_EQ(400, normal->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, normal->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, normal->fAPIStyle);
+
+ // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT,
+ // Typeface.ITALIC), Typeface.BOLD);
+ std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), Typeface::kBold));
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
// In Java,
- // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.ITALIC);
- std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
- EXPECT_EQ(4, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC),
+ // Typeface.ITALIC);
+ std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), Typeface::kItalic));
+ EXPECT_EQ(400, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java,
- // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.BOLD_ITALIC);
- std::unique_ptr<Typeface>
- boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
- EXPECT_EQ(7, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+ // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC),
+ // Typeface.BOLD_ITALIC);
+ std::unique_ptr<Typeface> boldItalic(
+ Typeface::createRelative(base.get(), Typeface::kBoldItalic));
+ EXPECT_EQ(700, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kBoldItalic, boldItalic->fAPIStyle);
}
TEST(TypefaceTest, createRelativeTest_fromSpecifiedStyled) {
@@ -245,174 +261,179 @@ TEST(TypefaceTest, createRelativeTest_fromSpecifiedStyled) {
// Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
// .setWeight(700).setItalic(false).build();
// Typeface.create(typeface, Typeface.NORMAL);
- std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
- EXPECT_EQ(4, normal->fStyle.getWeight());
- EXPECT_FALSE(normal->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+ std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), Typeface::kNormal));
+ EXPECT_EQ(400, normal->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, normal->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, normal->fAPIStyle);
// In Java,
// Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
// .setWeight(700).setItalic(false).build();
// Typeface.create(typeface, Typeface.BOLD);
- std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+ std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), Typeface::kBold));
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
// In Java,
// Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
// .setWeight(700).setItalic(false).build();
// Typeface.create(typeface, Typeface.ITALIC);
- std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
- EXPECT_EQ(4, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), Typeface::kItalic));
+ EXPECT_EQ(400, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java,
// Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
// .setWeight(700).setItalic(false).build();
// Typeface.create(typeface, Typeface.BOLD_ITALIC);
- std::unique_ptr<Typeface>
- boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
- EXPECT_EQ(7, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+ std::unique_ptr<Typeface> boldItalic(
+ Typeface::createRelative(base.get(), Typeface::kBoldItalic));
+ EXPECT_EQ(700, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kBoldItalic, boldItalic->fAPIStyle);
}
TEST(TypefaceTest, createAbsolute) {
// In Java,
- // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(400).setItalic(false)
+ // new
+ // Typeface.Builder(invalid).setFallback("sans-serif").setWeight(400).setItalic(false)
// .build();
std::unique_ptr<Typeface> regular(Typeface::createAbsolute(nullptr, 400, false));
- EXPECT_EQ(4, regular->fStyle.getWeight());
- EXPECT_FALSE(regular->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, regular->fSkiaStyle);
+ EXPECT_EQ(400, regular->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, regular->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, regular->fAPIStyle);
// In Java,
- // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(700).setItalic(false)
+ // new
+ // Typeface.Builder(invalid).setFallback("sans-serif").setWeight(700).setItalic(false)
// .build();
std::unique_ptr<Typeface> bold(Typeface::createAbsolute(nullptr, 700, false));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
// In Java,
- // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(400).setItalic(true)
+ // new
+ // Typeface.Builder(invalid).setFallback("sans-serif").setWeight(400).setItalic(true)
// .build();
std::unique_ptr<Typeface> italic(Typeface::createAbsolute(nullptr, 400, true));
- EXPECT_EQ(4, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ EXPECT_EQ(400, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java,
- // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(700).setItalic(true)
+ // new
+ // Typeface.Builder(invalid).setFallback("sans-serif").setWeight(700).setItalic(true)
// .build();
std::unique_ptr<Typeface> boldItalic(Typeface::createAbsolute(nullptr, 700, true));
- EXPECT_EQ(7, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+ EXPECT_EQ(700, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kBoldItalic, boldItalic->fAPIStyle);
// In Java,
- // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(1100).setItalic(true)
+ // new
+ // Typeface.Builder(invalid).setFallback("sans-serif").setWeight(1100).setItalic(true)
// .build();
std::unique_ptr<Typeface> over1000(Typeface::createAbsolute(nullptr, 1100, false));
- EXPECT_EQ(10, over1000->fStyle.getWeight());
- EXPECT_FALSE(over1000->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, over1000->fSkiaStyle);
+ EXPECT_EQ(1000, over1000->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, over1000->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, over1000->fAPIStyle);
}
TEST(TypefaceTest, createFromFamilies_Single) {
- // In Java, new Typeface.Builder("Roboto-Regular.ttf").setWeight(400).setItalic(false).build();
+ // In Java, new
+ // Typeface.Builder("Roboto-Regular.ttf").setWeight(400).setItalic(false).build();
std::unique_ptr<Typeface> regular(
Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoRegular), 400, false));
- EXPECT_EQ(4, regular->fStyle.getWeight());
- EXPECT_FALSE(regular->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, regular->fSkiaStyle);
+ EXPECT_EQ(400, regular->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, regular->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, regular->fAPIStyle);
- // In Java, new Typeface.Builder("Roboto-Bold.ttf").setWeight(700).setItalic(false).build();
+ // In Java, new
+ // Typeface.Builder("Roboto-Bold.ttf").setWeight(700).setItalic(false).build();
std::unique_ptr<Typeface> bold(
Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBold), 700, false));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
- // In Java, new Typeface.Builder("Roboto-Italic.ttf").setWeight(400).setItalic(true).build();
+ // In Java, new
+ // Typeface.Builder("Roboto-Italic.ttf").setWeight(400).setItalic(true).build();
std::unique_ptr<Typeface> italic(
Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoItalic), 400, true));
- EXPECT_EQ(4, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ EXPECT_EQ(400, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java,
- // new Typeface.Builder("Roboto-BoldItalic.ttf").setWeight(700).setItalic(true).build();
+ // new
+ // Typeface.Builder("Roboto-BoldItalic.ttf").setWeight(700).setItalic(true).build();
std::unique_ptr<Typeface> boldItalic(
Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBoldItalic), 700, true));
- EXPECT_EQ(7, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ EXPECT_EQ(700, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java,
- // new Typeface.Builder("Roboto-BoldItalic.ttf").setWeight(1100).setItalic(false).build();
+ // new
+ // Typeface.Builder("Roboto-BoldItalic.ttf").setWeight(1100).setItalic(false).build();
std::unique_ptr<Typeface> over1000(
Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBold), 1100, false));
- EXPECT_EQ(10, over1000->fStyle.getWeight());
- EXPECT_FALSE(over1000->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, over1000->fSkiaStyle);
+ EXPECT_EQ(1000, over1000->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, over1000->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, over1000->fAPIStyle);
}
TEST(TypefaceTest, createFromFamilies_Single_resolveByTable) {
// In Java, new Typeface.Builder("Roboto-Regular.ttf").build();
- std::unique_ptr<Typeface> regular(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoRegular),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
- EXPECT_EQ(4, regular->fStyle.getWeight());
- EXPECT_FALSE(regular->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kNormal, regular->fSkiaStyle);
+ std::unique_ptr<Typeface> regular(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoRegular), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ EXPECT_EQ(400, regular->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, regular->fStyle.slant());
+ EXPECT_EQ(Typeface::kNormal, regular->fAPIStyle);
// In Java, new Typeface.Builder("Roboto-Bold.ttf").build();
- std::unique_ptr<Typeface> bold(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBold),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
- EXPECT_EQ(7, bold->fStyle.getWeight());
- EXPECT_FALSE(bold->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+ std::unique_ptr<Typeface> bold(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoBold), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ EXPECT_EQ(700, bold->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, bold->fStyle.slant());
+ EXPECT_EQ(Typeface::kBold, bold->fAPIStyle);
// In Java, new Typeface.Builder("Roboto-Italic.ttf").build();
- std::unique_ptr<Typeface> italic(
- Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoItalic),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
- EXPECT_EQ(4, italic->fStyle.getWeight());
- EXPECT_TRUE(italic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ std::unique_ptr<Typeface> italic(Typeface::createFromFamilies(
+ makeSingleFamlyVector(kRobotoItalic), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ EXPECT_EQ(400, italic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, italic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
// In Java, new Typeface.Builder("Roboto-BoldItalic.ttf").build();
std::unique_ptr<Typeface> boldItalic(
Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBoldItalic),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
- EXPECT_EQ(7, boldItalic->fStyle.getWeight());
- EXPECT_TRUE(boldItalic->fStyle.getItalic());
- EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+ RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ EXPECT_EQ(700, boldItalic->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::ITALIC, boldItalic->fStyle.slant());
+ EXPECT_EQ(Typeface::kItalic, italic->fAPIStyle);
}
TEST(TypefaceTest, createFromFamilies_Family) {
std::vector<std::shared_ptr<minikin::FontFamily>> families = {
buildFamily(kRobotoRegular), buildFamily(kRobotoBold), buildFamily(kRobotoItalic),
- buildFamily(kRobotoBoldItalic)
- };
- std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(std::move(families),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
- EXPECT_EQ(4, typeface->fStyle.getWeight());
- EXPECT_FALSE(typeface->fStyle.getItalic());
+ buildFamily(kRobotoBoldItalic)};
+ std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(
+ std::move(families), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ EXPECT_EQ(400, typeface->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, typeface->fStyle.slant());
}
TEST(TypefaceTest, createFromFamilies_Family_withoutRegular) {
std::vector<std::shared_ptr<minikin::FontFamily>> families = {
- buildFamily(kRobotoBold), buildFamily(kRobotoItalic), buildFamily(kRobotoBoldItalic)
- };
- std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(std::move(families),
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
- EXPECT_EQ(7, typeface->fStyle.getWeight());
- EXPECT_FALSE(typeface->fStyle.getItalic());
+ buildFamily(kRobotoBold), buildFamily(kRobotoItalic), buildFamily(kRobotoBoldItalic)};
+ std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(
+ std::move(families), RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ EXPECT_EQ(700, typeface->fStyle.weight());
+ EXPECT_EQ(minikin::FontStyle::Slant::UPRIGHT, typeface->fStyle.slant());
}
} // namespace
diff --git a/libs/hwui/tests/unit/VectorDrawableAtlasTests.cpp b/libs/hwui/tests/unit/VectorDrawableAtlasTests.cpp
index 17f8176bcfdc..0c95fdd42851 100644
--- a/libs/hwui/tests/unit/VectorDrawableAtlasTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableAtlasTests.cpp
@@ -16,9 +16,9 @@
#include <gtest/gtest.h>
-#include "tests/common/TestUtils.h"
#include <GrRectanizer.h>
#include "pipeline/skia/VectorDrawableAtlas.h"
+#include "tests/common/TestUtils.h"
using namespace android;
using namespace android::uirenderer;
@@ -26,16 +26,16 @@ using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::skiapipeline;
RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, addGetRemove) {
- VectorDrawableAtlas atlas(100*100);
+ VectorDrawableAtlas atlas(100 * 100);
atlas.prepareForDraw(renderThread.getGrContext());
- //create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
+ // create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
const int MAX_RECTS = 150;
AtlasEntry VDRects[MAX_RECTS];
sk_sp<SkSurface> atlasSurface;
- //check we are able to allocate new rects
- //check that rects in the atlas do not intersect
+ // check we are able to allocate new rects
+ // check that rects in the atlas do not intersect
for (uint32_t i = 0; i < MAX_RECTS; i++) {
VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
if (0 == i) {
@@ -45,7 +45,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, addGetRemove) {
ASSERT_TRUE(VDRects[i].surface.get() != nullptr);
ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);
- //nothing in the atlas should intersect
+ // nothing in the atlas should intersect
if (atlasSurface.get() == VDRects[i].surface.get()) {
for (uint32_t j = 0; j < i; j++) {
if (atlasSurface.get() == VDRects[j].surface.get()) {
@@ -55,16 +55,16 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, addGetRemove) {
}
}
- //first 1/3 rects should all be in the same surface
- for (uint32_t i = 1; i < MAX_RECTS/3; i++) {
+ // first 1/3 rects should all be in the same surface
+ for (uint32_t i = 1; i < MAX_RECTS / 3; i++) {
ASSERT_NE(VDRects[i].key, VDRects[0].key);
ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
}
- //first rect is using atlas and last is a standalone surface
- ASSERT_NE(VDRects[0].surface.get(), VDRects[MAX_RECTS-1].surface.get());
+ // first rect is using atlas and last is a standalone surface
+ ASSERT_NE(VDRects[0].surface.get(), VDRects[MAX_RECTS - 1].surface.get());
- //check getEntry returns the same surfaces that we had created
+ // check getEntry returns the same surfaces that we had created
for (uint32_t i = 0; i < MAX_RECTS; i++) {
auto VDRect = atlas.getEntry(VDRects[i].key);
ASSERT_TRUE(VDRect.key != INVALID_ATLAS_KEY);
@@ -74,9 +74,9 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, addGetRemove) {
atlas.releaseEntry(VDRect.key);
}
- //check that any new rects will be allocated in the atlas, even that rectanizer is full.
- //rects in the atlas should not intersect.
- for (uint32_t i = 0; i < MAX_RECTS/3; i++) {
+ // check that any new rects will be allocated in the atlas, even that rectanizer is full.
+ // rects in the atlas should not intersect.
+ for (uint32_t i = 0; i < MAX_RECTS / 3; i++) {
VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
@@ -87,25 +87,24 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, addGetRemove) {
}
}
-
RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, disallowSharedSurface) {
- VectorDrawableAtlas atlas(100*100);
- //don't allow to use a shared surface
+ VectorDrawableAtlas atlas(100 * 100);
+ // don't allow to use a shared surface
atlas.setStorageMode(VectorDrawableAtlas::StorageMode::disallowSharedSurface);
atlas.prepareForDraw(renderThread.getGrContext());
- //create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
+ // create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
const int MAX_RECTS = 150;
AtlasEntry VDRects[MAX_RECTS];
- //check we are able to allocate new rects
- //check that rects in the atlas use unique surfaces
+ // check we are able to allocate new rects
+ // check that rects in the atlas use unique surfaces
for (uint32_t i = 0; i < MAX_RECTS; i++) {
VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
ASSERT_TRUE(VDRects[i].surface.get() != nullptr);
ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);
- //nothing in the atlas should use the same surface
+ // nothing in the atlas should use the same surface
for (uint32_t j = 0; j < i; j++) {
ASSERT_NE(VDRects[i].surface.get(), VDRects[j].surface.get());
}
@@ -113,17 +112,17 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, disallowSharedSurface) {
}
RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, repack) {
- VectorDrawableAtlas atlas(100*100);
+ VectorDrawableAtlas atlas(100 * 100);
ASSERT_FALSE(atlas.isFragmented());
atlas.prepareForDraw(renderThread.getGrContext());
ASSERT_FALSE(atlas.isFragmented());
- //create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
+ // create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
const int MAX_RECTS = 150;
AtlasEntry VDRects[MAX_RECTS];
sk_sp<SkSurface> atlasSurface;
- //fill the atlas with check we are able to allocate new rects
+ // fill the atlas with check we are able to allocate new rects
for (uint32_t i = 0; i < MAX_RECTS; i++) {
VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
if (0 == i) {
@@ -134,13 +133,13 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, repack) {
ASSERT_FALSE(atlas.isFragmented());
- //first 1/3 rects should all be in the same surface
- for (uint32_t i = 1; i < MAX_RECTS/3; i++) {
+ // first 1/3 rects should all be in the same surface
+ for (uint32_t i = 1; i < MAX_RECTS / 3; i++) {
ASSERT_NE(VDRects[i].key, VDRects[0].key);
ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
}
- //release all entries
+ // release all entries
for (uint32_t i = 0; i < MAX_RECTS; i++) {
auto VDRect = atlas.getEntry(VDRects[i].key);
ASSERT_TRUE(VDRect.key != INVALID_ATLAS_KEY);
@@ -149,9 +148,9 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, repack) {
ASSERT_FALSE(atlas.isFragmented());
- //allocate 4x4 rects, which will fragment the atlas badly, because each entry occupies a 10x10
- //area
- for (uint32_t i = 0; i < 4*MAX_RECTS; i++) {
+ // allocate 4x4 rects, which will fragment the atlas badly, because each entry occupies a 10x10
+ // area
+ for (uint32_t i = 0; i < 4 * MAX_RECTS; i++) {
AtlasEntry entry = atlas.requestNewEntry(4, 4, renderThread.getGrContext());
ASSERT_TRUE(entry.key != INVALID_ATLAS_KEY);
}
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index 1c2156765fe6..02f740cee096 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -33,195 +33,200 @@ struct TestData {
};
const static TestData sTestDataSet[] = {
- // TestData with scientific notation -2e3 etc.
- {
- // Path
- "M2.000000,22.000000l20.000000,0.000000 1e0-2e3z",
- {
- // Verbs
- {'M', 'l', 'z'},
- // Verb sizes
- {2, 4, 0},
- // Points
- {2, 22, 20, 0, 1, -2000},
- },
- [](SkPath* outPath) {
- outPath->moveTo(2, 22);
- outPath->rLineTo(20, 0);
- outPath->rLineTo(1, -2000);
- outPath->close();
- outPath->moveTo(2, 22);
- }
- },
-
- // Comprehensive data, containing all the verbs possible.
- {
- // Path
- "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10",
- {
- // Verbs
- {'M', 'm', 'l', 'L', 'H', 'h', 'V', 'v', 'Q', 'q', 't', 'T', 'C', 'c', 'S', 's', 'A', 'a'},
- // VerbSizes
- {2, 2, 2, 2, 1, 1, 1, 1, 4, 4, 2, 2, 6, 6, 4, 4, 7, 7},
- // Points
- {1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 5.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, 0.0, 1.0, 1.0, 10.0, 10.0, 10.0, 10.0, 0.0, 1.0, 1.0, 10.0, 10.0, }
- },
- [](SkPath* outPath) {
- outPath->moveTo(1.0, 1.0);
- outPath->rMoveTo(2.0, 2.0);
- outPath->rLineTo(3.0, 3.0);
- outPath->lineTo(3.0, 3.0);
- outPath->lineTo(4.0, 3.0);
- outPath->rLineTo(4.0, 0);
- outPath->lineTo(8.0, 5.0);
- outPath->rLineTo(0, 5.0);
- outPath->quadTo(6.0, 6.0, 6.0, 6.0);
- outPath->rQuadTo(6.0, 6.0, 6.0, 6.0);
- outPath->rQuadTo(0.0, 0.0, 7.0, 7.0);
- outPath->quadTo(26.0, 26.0, 7.0, 7.0);
- outPath->cubicTo(8.0, 8.0, 8.0, 8.0, 8.0, 8.0);
- outPath->rCubicTo(8.0, 8.0, 8.0, 8.0, 8.0, 8.0);
- outPath->cubicTo(16.0, 16.0, 9.0, 9.0, 9.0, 9.0);
- outPath->rCubicTo(0.0, 0.0, 9.0, 9.0, 9.0, 9.0);
- outPath->cubicTo(18.447775037328352, 20.404243860300607, 17.998389141249767, 22.8911717921705, 16.737515350332117, 24.986664170401575);
- outPath->cubicTo(15.476641559414468, 27.08215654863265, 13.489843598291483, 28.644011882390082, 11.155893964798905, 29.37447073281729);
- outPath->cubicTo(8.821944331306327, 30.1049295832445, 6.299226382436471, 29.954422532383525, 4.0686829203897235, 28.951642951534332);
- outPath->cubicTo(1.838139458342976, 27.94886337068514, 0.05113662931485696, 26.161860541657013, -0.9516429515343354, 23.931317079610267);
- outPath->cubicTo(-1.9544225323835278, 21.70077361756352, -2.1049295832444987, 19.178055668693663, -1.37447073281729, 16.844106035201087);
- outPath->cubicTo(-0.6440118823900814, 14.51015640170851, 0.9178434513673546, 12.523358440585524, 3.0133358295984305, 11.262484649667876);
- outPath->cubicTo(5.108828207829506, 10.001610858750228, 7.5957561396993984, 9.552224962671648, 10.000000000000005, 10.0);
- outPath->cubicTo(10.0, 7.348852265086975, 11.054287646850167, 4.803576729418881, 12.928932188134523, 2.9289321881345254);
- outPath->cubicTo(14.803576729418879, 1.0542876468501696, 17.348852265086972, 4.870079381441987E-16, 19.999999999999996, 0.0);
- outPath->cubicTo(22.65114773491302, -4.870079381441987E-16, 25.19642327058112, 1.0542876468501678, 27.071067811865476, 2.9289321881345227);
- outPath->cubicTo(28.94571235314983, 4.803576729418878, 30.0, 7.348852265086974, 30.0, 9.999999999999998);
- outPath->cubicTo(30.0, 12.651147734913023, 28.94571235314983, 15.19642327058112, 27.071067811865476, 17.071067811865476);
- outPath->cubicTo(25.19642327058112, 18.94571235314983, 22.651147734913028, 20.0, 20.000000000000004, 20.0);
- }
- },
-
- // Check box VectorDrawable path data
- {
- // Path
- "M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z",
- {
- {'M', 'l', 'c', 'l', 'c', 'l', 'c', 'l', 'c', 'Z', 'M', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'Z'},
- {2, 2, 6, 2, 6, 2, 6, 2, 6, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0},
- {0.0, -1.0, 0.0, 0.0, 0.5522848, 0.0, 1.0, 0.44771525, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5522848, -0.44771525, 1.0, -1.0, 1.0, 0.0, 0.0, -0.5522848, 0.0, -1.0, -0.44771525, -1.0, -1.0, 0.0, 0.0, 0.0, -0.5522848, 0.44771525, -1.0, 1.0, -1.0, 7.0, -9.0, 0.0, 0.0, -14.0, 0.0, -14.0, 0.0, -1.1044922, 0.0, -2.0, 0.8955078, -2.0, 2.0, 0.0, 0.0, 0.0, 14.0, 0.0, 14.0, 0.0, 1.1044922, 0.8955078, 2.0, 2.0, 2.0, 0.0, 0.0, 14.0, 0.0, 14.0, 0.0, 1.1044922, 0.0, 2.0, -0.8955078, 2.0, -2.0, 0.0, 0.0, 0.0, -14.0, 0.0, -14.0, 0.0, -1.1044922, -0.8955078, -2.0, -2.0, -2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- },
- [](SkPath* outPath) {
- outPath->moveTo(0.0, -1.0);
- outPath->rLineTo(0.0, 0.0);
- outPath->rCubicTo(0.5522848, 0.0, 1.0, 0.44771525, 1.0, 1.0);
- outPath->rLineTo(0.0, 0.0);
- outPath->rCubicTo(0.0, 0.5522848, -0.44771525, 1.0, -1.0, 1.0);
- outPath->rLineTo(0.0, 0.0);
- outPath->rCubicTo(-0.5522848, 0.0, -1.0, -0.44771525, -1.0, -1.0);
- outPath->rLineTo(0.0, 0.0);
- outPath->rCubicTo(0.0, -0.5522848, 0.44771525, -1.0, 1.0, -1.0);
- outPath->close();
- outPath->moveTo(0.0, -1.0);
- outPath->moveTo(7.0, -9.0);
- outPath->rCubicTo(0.0, 0.0, -14.0, 0.0, -14.0, 0.0);
- outPath->rCubicTo(-1.1044922, 0.0, -2.0, 0.8955078, -2.0, 2.0);
- outPath->rCubicTo(0.0, 0.0, 0.0, 14.0, 0.0, 14.0);
- outPath->rCubicTo(0.0, 1.1044922, 0.8955078, 2.0, 2.0, 2.0);
- outPath->rCubicTo(0.0, 0.0, 14.0, 0.0, 14.0, 0.0);
- outPath->rCubicTo(1.1044922, 0.0, 2.0, -0.8955078, 2.0, -2.0);
- outPath->rCubicTo(0.0, 0.0, 0.0, -14.0, 0.0, -14.0);
- outPath->rCubicTo(0.0, -1.1044922, -0.8955078, -2.0, -2.0, -2.0);
- outPath->rCubicTo(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
- outPath->close();
- outPath->moveTo(7.0, -9.0);
- }
- },
-
- // pie1 in progress bar
- {
- "M300,70 a230,230 0 1,0 1,0 z",
- {
- {'M', 'a', 'z', },
- {2, 7, 0, },
- {300.0, 70.0, 230.0, 230.0, 0.0, 1.0, 0.0, 1.0, 0.0, },
- },
- [](SkPath* outPath) {
- outPath->moveTo(300.0, 70.0);
- outPath->cubicTo(239.06697794203706, 70.13246340443499, 180.6164396449267, 94.47383115953485, 137.6004913602211, 137.6302781499585);
- outPath->cubicTo(94.58454307551551, 180.78672514038215, 70.43390412842275, 239.3163266242308, 70.50013586976587, 300.2494566687817);
- outPath->cubicTo(70.56636761110899, 361.1825867133326, 94.84418775550249, 419.65954850554147, 137.9538527586204, 462.72238058830936);
- outPath->cubicTo(181.06351776173827, 505.7852126710772, 239.5668339599056, 529.999456521097, 300.49999999999994, 529.999456521097);
- outPath->cubicTo(361.43316604009436, 529.999456521097, 419.93648223826176, 505.78521267107726, 463.0461472413797, 462.7223805883093);
- outPath->cubicTo(506.1558122444976, 419.65954850554135, 530.433632388891, 361.1825867133324, 530.4998641302341, 300.2494566687815);
- outPath->cubicTo(530.5660958715771, 239.31632662423056, 506.4154569244844, 180.7867251403819, 463.3995086397787, 137.6302781499583);
- outPath->cubicTo(420.383560355073, 94.47383115953468, 361.93302205796255, 70.13246340443492, 300.9999999999996, 70.00000000000003);
- outPath->close();
- outPath->moveTo(300.0, 70.0);
- }
- },
-
- // Random long data
- {
- // Path
- "M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z",
- {
- // Verbs
- {'M', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'C', 'z'},
- // Verb sizes
- {2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0},
- // Points
- {5.3, 13.2, -0.1, 0, -0.3, 0, -0.4, -0.1, -0.3, -0.2, -0.4, -0.7, -0.2, -1, 1.3, -1.9, 2.9, -3.4, 4.9, -4.5, 4.1, -2.2, 9.3, -2.2, 13.4, 0, 1.9, 1.1, 3.6, 2.5, 4.9, 4.4, 0.2, 0.3, 0.1, 0.8, -0.2, 1, -0.3, 0.2, -0.8, 0.1, -1, -0.2, -1.2, -1.7, -2.6, -3, -4.3, -4, -3.7, -2, -8.3, -2, -12, 0, -1.7, 0.9, -3.2, 2.3, -4.3, 4, 5.7, 13.1, 5.5, 13.2, 5.3, 13.2},
- },
- [](SkPath* outPath) {
- outPath->moveTo(5.3, 13.2);
- outPath->rCubicTo(-0.1, 0.0, -0.3, 0.0, -0.4, -0.1);
- outPath->rCubicTo(-0.3, -0.2, -0.4, -0.7, -0.2, -1.0);
- outPath->rCubicTo(1.3, -1.9, 2.9, -3.4, 4.9, -4.5);
- outPath->rCubicTo(4.1, -2.2, 9.3, -2.2, 13.4, 0.0);
- outPath->rCubicTo(1.9, 1.1, 3.6, 2.5, 4.9, 4.4);
- outPath->rCubicTo(0.2, 0.3, 0.1, 0.8, -0.2, 1.0);
- outPath->rCubicTo(-0.3, 0.2, -0.8, 0.1, -1.0, -0.2);
- outPath->rCubicTo(-1.2, -1.7, -2.6, -3.0, -4.3, -4.0);
- outPath->rCubicTo(-3.7, -2.0, -8.3, -2.0, -12.0, 0.0);
- outPath->rCubicTo(-1.7, 0.9, -3.2, 2.3, -4.3, 4.0);
- outPath->cubicTo(5.7, 13.1, 5.5, 13.2, 5.3, 13.2);
- outPath->close();
- outPath->moveTo(5.3, 13.2);
- }
- },
-
- // Extreme case with numbers and decimal points crunched together
- {
- // Path
- "l0.0.0.5.0.0.5-0.5.0.0-.5z",
- {
- // Verbs
- {'l', 'z'},
- // Verb sizes
- {10, 0},
- // Points
- {0, 0, 0.5, 0, 0, 0.5, -0.5, 0, 0, -0.5},
- },
- [](SkPath* outPath) {
- outPath->rLineTo(0.0, 0.0);
- outPath->rLineTo(0.5, 0.0);
- outPath->rLineTo(0.0, 0.5);
- outPath->rLineTo(-0.5, 0.0);
- outPath->rLineTo(0.0, -0.5);
- outPath->close();
- outPath->moveTo(0.0, 0.0);
- }
- },
-
- // Empty test data
- {
- "",
- {
- // Verbs
- {},
- {},
- {},
- },
- [](SkPath* outPath) {}
- }
+ // TestData with scientific notation -2e3 etc.
+ {// Path
+ "M2.000000,22.000000l20.000000,0.000000 1e0-2e3z",
+ {
+ // Verbs
+ {'M', 'l', 'z'},
+ // Verb sizes
+ {2, 4, 0},
+ // Points
+ {2, 22, 20, 0, 1, -2000},
+ },
+ [](SkPath* outPath) {
+ outPath->moveTo(2, 22);
+ outPath->rLineTo(20, 0);
+ outPath->rLineTo(1, -2000);
+ outPath->close();
+ outPath->moveTo(2, 22);
+ }},
+
+ // Comprehensive data, containing all the verbs possible.
+ {// Path
+ "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 "
+ "8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10",
+ {// Verbs
+ {'M', 'm', 'l', 'L', 'H', 'h', 'V', 'v', 'Q', 'q', 't', 'T', 'C', 'c', 'S', 's', 'A',
+ 'a'},
+ // VerbSizes
+ {2, 2, 2, 2, 1, 1, 1, 1, 4, 4, 2, 2, 6, 6, 4, 4, 7, 7},
+ // Points
+ {
+ 1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 5.0, 5.0, 6.0, 6.0, 6.0,
+ 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0,
+ 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0,
+ 10.0, 0.0, 1.0, 1.0, 10.0, 10.0, 10.0, 10.0, 0.0, 1.0, 1.0, 10.0, 10.0,
+ }},
+ [](SkPath* outPath) {
+ outPath->moveTo(1.0, 1.0);
+ outPath->rMoveTo(2.0, 2.0);
+ outPath->rLineTo(3.0, 3.0);
+ outPath->lineTo(3.0, 3.0);
+ outPath->lineTo(4.0, 3.0);
+ outPath->rLineTo(4.0, 0);
+ outPath->lineTo(8.0, 5.0);
+ outPath->rLineTo(0, 5.0);
+ outPath->quadTo(6.0, 6.0, 6.0, 6.0);
+ outPath->rQuadTo(6.0, 6.0, 6.0, 6.0);
+ outPath->rQuadTo(0.0, 0.0, 7.0, 7.0);
+ outPath->quadTo(26.0, 26.0, 7.0, 7.0);
+ outPath->cubicTo(8.0, 8.0, 8.0, 8.0, 8.0, 8.0);
+ outPath->rCubicTo(8.0, 8.0, 8.0, 8.0, 8.0, 8.0);
+ outPath->cubicTo(16.0, 16.0, 9.0, 9.0, 9.0, 9.0);
+ outPath->rCubicTo(0.0, 0.0, 9.0, 9.0, 9.0, 9.0);
+ outPath->arcTo(10.0, 10.0, 0.0, SkPath::kLarge_ArcSize, SkPath::kCW_Direction, 10.0, 10.0);
+ outPath->arcTo(10.0, 10.0, 0.0, SkPath::kLarge_ArcSize, SkPath::kCW_Direction, 20.0, 20.0);
+ }},
+
+ // Check box VectorDrawable path data
+ {// Path
+ "M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c "
+ "0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 "
+ "-1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z "
+ "M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 "
+ "c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 "
+ "14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 "
+ "0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z",
+ {
+ {'M', 'l', 'c', 'l', 'c', 'l', 'c', 'l', 'c', 'Z', 'M',
+ 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'Z'},
+ {2, 2, 6, 2, 6, 2, 6, 2, 6, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0},
+ {0.0, -1.0, 0.0, 0.0, 0.5522848, 0.0, 1.0,
+ 0.44771525, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5522848,
+ -0.44771525, 1.0, -1.0, 1.0, 0.0, 0.0, -0.5522848,
+ 0.0, -1.0, -0.44771525, -1.0, -1.0, 0.0, 0.0,
+ 0.0, -0.5522848, 0.44771525, -1.0, 1.0, -1.0, 7.0,
+ -9.0, 0.0, 0.0, -14.0, 0.0, -14.0, 0.0,
+ -1.1044922, 0.0, -2.0, 0.8955078, -2.0, 2.0, 0.0,
+ 0.0, 0.0, 14.0, 0.0, 14.0, 0.0, 1.1044922,
+ 0.8955078, 2.0, 2.0, 2.0, 0.0, 0.0, 14.0,
+ 0.0, 14.0, 0.0, 1.1044922, 0.0, 2.0, -0.8955078,
+ 2.0, -2.0, 0.0, 0.0, 0.0, -14.0, 0.0,
+ -14.0, 0.0, -1.1044922, -0.8955078, -2.0, -2.0, -2.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ },
+ [](SkPath* outPath) {
+ outPath->moveTo(0.0, -1.0);
+ outPath->rLineTo(0.0, 0.0);
+ outPath->rCubicTo(0.5522848, 0.0, 1.0, 0.44771525, 1.0, 1.0);
+ outPath->rLineTo(0.0, 0.0);
+ outPath->rCubicTo(0.0, 0.5522848, -0.44771525, 1.0, -1.0, 1.0);
+ outPath->rLineTo(0.0, 0.0);
+ outPath->rCubicTo(-0.5522848, 0.0, -1.0, -0.44771525, -1.0, -1.0);
+ outPath->rLineTo(0.0, 0.0);
+ outPath->rCubicTo(0.0, -0.5522848, 0.44771525, -1.0, 1.0, -1.0);
+ outPath->close();
+ outPath->moveTo(0.0, -1.0);
+ outPath->moveTo(7.0, -9.0);
+ outPath->rCubicTo(0.0, 0.0, -14.0, 0.0, -14.0, 0.0);
+ outPath->rCubicTo(-1.1044922, 0.0, -2.0, 0.8955078, -2.0, 2.0);
+ outPath->rCubicTo(0.0, 0.0, 0.0, 14.0, 0.0, 14.0);
+ outPath->rCubicTo(0.0, 1.1044922, 0.8955078, 2.0, 2.0, 2.0);
+ outPath->rCubicTo(0.0, 0.0, 14.0, 0.0, 14.0, 0.0);
+ outPath->rCubicTo(1.1044922, 0.0, 2.0, -0.8955078, 2.0, -2.0);
+ outPath->rCubicTo(0.0, 0.0, 0.0, -14.0, 0.0, -14.0);
+ outPath->rCubicTo(0.0, -1.1044922, -0.8955078, -2.0, -2.0, -2.0);
+ outPath->rCubicTo(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+ outPath->close();
+ outPath->moveTo(7.0, -9.0);
+ }},
+
+ // pie1 in progress bar
+ {"M300,70 a230,230 0 1,0 1,0 z",
+ {
+ {
+ 'M', 'a', 'z',
+ },
+ {
+ 2, 7, 0,
+ },
+ {
+ 300.0, 70.0, 230.0, 230.0, 0.0, 1.0, 0.0, 1.0, 0.0,
+ },
+ },
+ [](SkPath* outPath) {
+ outPath->moveTo(300.0, 70.0);
+ outPath->arcTo(230.0, 230.0, 0.0, SkPath::kLarge_ArcSize, SkPath::kCCW_Direction, 301.0, 70.0);
+ outPath->close();
+ outPath->moveTo(300.0, 70.0);
+ }},
+
+ // Random long data
+ {// Path
+ "M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 "
+ "4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 "
+ "-0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 "
+ "-12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z",
+ {
+ // Verbs
+ {'M', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'C', 'z'},
+ // Verb sizes
+ {2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0},
+ // Points
+ {5.3, 13.2, -0.1, 0, -0.3, 0, -0.4, -0.1, -0.3, -0.2, -0.4, -0.7, -0.2, -1,
+ 1.3, -1.9, 2.9, -3.4, 4.9, -4.5, 4.1, -2.2, 9.3, -2.2, 13.4, 0, 1.9, 1.1,
+ 3.6, 2.5, 4.9, 4.4, 0.2, 0.3, 0.1, 0.8, -0.2, 1, -0.3, 0.2, -0.8, 0.1,
+ -1, -0.2, -1.2, -1.7, -2.6, -3, -4.3, -4, -3.7, -2, -8.3, -2, -12, 0,
+ -1.7, 0.9, -3.2, 2.3, -4.3, 4, 5.7, 13.1, 5.5, 13.2, 5.3, 13.2},
+ },
+ [](SkPath* outPath) {
+ outPath->moveTo(5.3, 13.2);
+ outPath->rCubicTo(-0.1, 0.0, -0.3, 0.0, -0.4, -0.1);
+ outPath->rCubicTo(-0.3, -0.2, -0.4, -0.7, -0.2, -1.0);
+ outPath->rCubicTo(1.3, -1.9, 2.9, -3.4, 4.9, -4.5);
+ outPath->rCubicTo(4.1, -2.2, 9.3, -2.2, 13.4, 0.0);
+ outPath->rCubicTo(1.9, 1.1, 3.6, 2.5, 4.9, 4.4);
+ outPath->rCubicTo(0.2, 0.3, 0.1, 0.8, -0.2, 1.0);
+ outPath->rCubicTo(-0.3, 0.2, -0.8, 0.1, -1.0, -0.2);
+ outPath->rCubicTo(-1.2, -1.7, -2.6, -3.0, -4.3, -4.0);
+ outPath->rCubicTo(-3.7, -2.0, -8.3, -2.0, -12.0, 0.0);
+ outPath->rCubicTo(-1.7, 0.9, -3.2, 2.3, -4.3, 4.0);
+ outPath->cubicTo(5.7, 13.1, 5.5, 13.2, 5.3, 13.2);
+ outPath->close();
+ outPath->moveTo(5.3, 13.2);
+ }},
+
+ // Extreme case with numbers and decimal points crunched together
+ {// Path
+ "l0.0.0.5.0.0.5-0.5.0.0-.5z",
+ {
+ // Verbs
+ {'l', 'z'},
+ // Verb sizes
+ {10, 0},
+ // Points
+ {0, 0, 0.5, 0, 0, 0.5, -0.5, 0, 0, -0.5},
+ },
+ [](SkPath* outPath) {
+ outPath->rLineTo(0.0, 0.0);
+ outPath->rLineTo(0.5, 0.0);
+ outPath->rLineTo(0.0, 0.5);
+ outPath->rLineTo(-0.5, 0.0);
+ outPath->rLineTo(0.0, -0.5);
+ outPath->close();
+ outPath->moveTo(0.0, 0.0);
+ }},
+
+ // Empty test data
+ {"",
+ {
+ // Verbs
+ {},
+ {},
+ {},
+ },
+ [](SkPath* outPath) {}}
};
@@ -231,22 +236,22 @@ struct StringPath {
};
const StringPath sStringPaths[] = {
- {"3e...3", false}, // Not starting with a verb and ill-formatted float
- {"L.M.F.A.O", false}, // No floats following verbs
- {"m 1 1", true}, // Valid path data
- {"\n \t z", true}, // Valid path data with leading spaces
- {"1-2e34567", false}, // Not starting with a verb and ill-formatted float
- {"f 4 5", false}, // Invalid verb
- {"\r ", false} // Empty string
+ {"3e...3", false}, // Not starting with a verb and ill-formatted float
+ {"L.M.F.A.O", false}, // No floats following verbs
+ {"m 1 1", true}, // Valid path data
+ {"\n \t z", true}, // Valid path data with leading spaces
+ {"1-2e34567", false}, // Not starting with a verb and ill-formatted float
+ {"f 4 5", false}, // Invalid verb
+ {"\r ", false}, // Empty string
+ {"L1,0 L1,1 L0,1 z M1000", false} // Not enough floats following verb M.
};
-
static bool hasSameVerbs(const PathData& from, const PathData& to) {
return from.verbs == to.verbs && from.verbSizes == to.verbSizes;
}
TEST(PathParser, parseStringForData) {
- for (TestData testData: sTestDataSet) {
+ for (TestData testData : sTestDataSet) {
PathParser::ParseResult result;
// Test generated path data against the given data.
PathData pathData;
@@ -259,14 +264,14 @@ TEST(PathParser, parseStringForData) {
PathParser::ParseResult result;
PathData pathData;
SkPath skPath;
- PathParser::getPathDataFromAsciiString(&pathData, &result,
- stringPath.stringPath, strlen(stringPath.stringPath));
+ PathParser::getPathDataFromAsciiString(&pathData, &result, stringPath.stringPath,
+ strlen(stringPath.stringPath));
EXPECT_EQ(stringPath.isValid, !result.failureOccurred);
}
}
TEST(VectorDrawableUtils, createSkPathFromPathData) {
- for (TestData testData: sTestDataSet) {
+ for (TestData testData : sTestDataSet) {
SkPath expectedPath;
testData.skPathLamda(&expectedPath);
SkPath actualPath;
@@ -276,7 +281,7 @@ TEST(VectorDrawableUtils, createSkPathFromPathData) {
}
TEST(PathParser, parseAsciiStringForSkPath) {
- for (TestData testData: sTestDataSet) {
+ for (TestData testData : sTestDataSet) {
PathParser::ParseResult result;
size_t length = strlen(testData.pathString);
// Check the return value as well as the SkPath generated.
@@ -293,14 +298,14 @@ TEST(PathParser, parseAsciiStringForSkPath) {
PathParser::ParseResult result;
SkPath skPath;
PathParser::parseAsciiStringForSkPath(&skPath, &result, stringPath.stringPath,
- strlen(stringPath.stringPath));
+ strlen(stringPath.stringPath));
EXPECT_EQ(stringPath.isValid, !result.failureOccurred);
}
}
TEST(VectorDrawableUtils, morphPathData) {
- for (TestData fromData: sTestDataSet) {
- for (TestData toData: sTestDataSet) {
+ for (TestData fromData : sTestDataSet) {
+ for (TestData toData : sTestDataSet) {
bool canMorph = VectorDrawableUtils::canMorph(fromData.pathData, toData.pathData);
if (fromData.pathData == toData.pathData) {
EXPECT_TRUE(canMorph);
@@ -314,11 +319,11 @@ TEST(VectorDrawableUtils, morphPathData) {
TEST(VectorDrawableUtils, interpolatePathData) {
// Interpolate path data with itself and every other path data
- for (TestData fromData: sTestDataSet) {
- for (TestData toData: sTestDataSet) {
+ for (TestData fromData : sTestDataSet) {
+ for (TestData toData : sTestDataSet) {
PathData outData;
bool success = VectorDrawableUtils::interpolatePathData(&outData, fromData.pathData,
- toData.pathData, 0.5);
+ toData.pathData, 0.5);
bool expectedToMorph = hasSameVerbs(fromData.pathData, toData.pathData);
EXPECT_EQ(expectedToMorph, success);
}
@@ -335,12 +340,12 @@ TEST(VectorDrawableUtils, interpolatePathData) {
PathData outData;
// Interpolate the two path data with different fractions
for (float fraction : fractions) {
- bool success = VectorDrawableUtils::interpolatePathData(
- &outData, fromPathData, toPathData, fraction);
+ bool success = VectorDrawableUtils::interpolatePathData(&outData, fromPathData,
+ toPathData, fraction);
EXPECT_TRUE(success);
for (size_t i = 0; i < outData.points.size(); i++) {
- float expectedResult = fromPathData.points[i] * (1.0 - fraction) +
- toPathData.points[i] * fraction;
+ float expectedResult =
+ fromPathData.points[i] * (1.0 - fraction) + toPathData.points[i] * fraction;
EXPECT_TRUE(MathUtils::areEqual(expectedResult, outData.points[i]));
}
}
@@ -348,7 +353,7 @@ TEST(VectorDrawableUtils, interpolatePathData) {
}
TEST(VectorDrawable, groupProperties) {
- //TODO: Also need to test property sync and dirty flag when properties change.
+ // TODO: Also need to test property sync and dirty flag when properties change.
VectorDrawable::Group group;
VectorDrawable::Group::GroupProperties* properties = group.mutateProperties();
// Test default values, change values through setters and verify the change through getters.
@@ -379,7 +384,6 @@ TEST(VectorDrawable, groupProperties) {
EXPECT_EQ(0.0f, properties->getPivotY());
properties->setPivotY(1.0f);
EXPECT_EQ(1.0f, properties->getPivotY());
-
}
TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) {
@@ -402,5 +406,5 @@ TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) {
EXPECT_TRUE(shader->unique());
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index cea84c057b63..9e6d9a8c27de 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-#include "gtest/gtest.h"
#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "Caches.h"
#include "debug/GlesDriver.h"
#include "debug/NullGlesDriver.h"
#include "hwui/Typeface.h"
-#include "thread/TaskManager.h"
+#include "Properties.h"
#include "tests/common/LeakChecker.h"
+#include "thread/TaskManager.h"
#include <signal.h>
@@ -31,17 +32,14 @@ using namespace android;
using namespace android::uirenderer;
static auto CRASH_SIGNALS = {
- SIGABRT,
- SIGSEGV,
- SIGBUS,
+ SIGABRT, SIGSEGV, SIGBUS,
};
static map<int, struct sigaction> gSigChain;
static void gtestSigHandler(int sig, siginfo_t* siginfo, void* context) {
auto testinfo = ::testing::UnitTest::GetInstance()->current_test_info();
- printf("[ FAILED ] %s.%s\n", testinfo->test_case_name(),
- testinfo->name());
+ printf("[ FAILED ] %s.%s\n", testinfo->test_case_name(), testinfo->name());
printf("[ FATAL! ] Process crashed, aborting tests!\n");
fflush(stdout);
@@ -53,9 +51,7 @@ static void gtestSigHandler(int sig, siginfo_t* siginfo, void* context) {
class TypefaceEnvironment : public testing::Environment {
public:
- virtual void SetUp() {
- Typeface::setRobotoTypefaceForTest();
- }
+ virtual void SetUp() { Typeface::setRobotoTypefaceForTest(); }
};
int main(int argc, char* argv[]) {
@@ -72,6 +68,7 @@ int main(int argc, char* argv[]) {
// Replace the default GLES driver
debug::GlesDriver::replace(std::make_unique<debug::NullGlesDriver>());
+ Properties::isolatedProcess = true;
// Run the tests
testing::InitGoogleTest(&argc, argv);
@@ -83,4 +80,3 @@ int main(int argc, char* argv[]) {
test::LeakChecker::checkForLeaks();
return ret;
}
-
diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h
index 17f82ba9d67d..8faeee6b391a 100644
--- a/libs/hwui/thread/Barrier.h
+++ b/libs/hwui/thread/Barrier.h
@@ -24,8 +24,9 @@ namespace uirenderer {
class Barrier {
public:
- explicit Barrier(Condition::WakeUpType type = Condition::WAKE_UP_ALL) : mType(type), mOpened(false) { }
- ~Barrier() { }
+ explicit Barrier(Condition::WakeUpType type = Condition::WAKE_UP_ALL)
+ : mType(type), mOpened(false) {}
+ ~Barrier() {}
void open() {
Mutex::Autolock l(mLock);
@@ -47,7 +48,7 @@ private:
mutable Condition mCondition;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_BARRIER_H
+#endif // ANDROID_HWUI_BARRIER_H
diff --git a/libs/hwui/thread/Future.h b/libs/hwui/thread/Future.h
index 177eebd9b85f..45f3102492e3 100644
--- a/libs/hwui/thread/Future.h
+++ b/libs/hwui/thread/Future.h
@@ -24,11 +24,12 @@
namespace android {
namespace uirenderer {
-template<typename T>
-class Future: public LightRefBase<Future<T> > {
+template <typename T>
+class Future : public LightRefBase<Future<T> > {
public:
- explicit Future(Condition::WakeUpType type = Condition::WAKE_UP_ONE): mBarrier(type), mResult() { }
- ~Future() { }
+ explicit Future(Condition::WakeUpType type = Condition::WAKE_UP_ONE)
+ : mBarrier(type), mResult() {}
+ ~Future() {}
/**
* Returns the result of this future, blocking if
@@ -52,7 +53,7 @@ private:
T mResult;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_FUTURE_H
+#endif // ANDROID_HWUI_FUTURE_H
diff --git a/libs/hwui/thread/Signal.h b/libs/hwui/thread/Signal.h
index 93e6f4c27535..ffcd4b675a85 100644
--- a/libs/hwui/thread/Signal.h
+++ b/libs/hwui/thread/Signal.h
@@ -26,8 +26,9 @@ namespace uirenderer {
class Signal {
public:
- explicit Signal(Condition::WakeUpType type = Condition::WAKE_UP_ALL) : mType(type), mSignaled(false) { }
- ~Signal() { }
+ explicit Signal(Condition::WakeUpType type = Condition::WAKE_UP_ALL)
+ : mType(type), mSignaled(false) {}
+ ~Signal() {}
void signal() {
{
@@ -52,7 +53,7 @@ private:
mutable Condition mCondition;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_SIGNAL_H
+#endif // ANDROID_HWUI_SIGNAL_H
diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h
index 7fcf5931c4b4..276a22f941fe 100644
--- a/libs/hwui/thread/Task.h
+++ b/libs/hwui/thread/Task.h
@@ -25,36 +25,30 @@
namespace android {
namespace uirenderer {
-class TaskBase: public RefBase {
+class TaskBase : public RefBase {
public:
- TaskBase() { }
- virtual ~TaskBase() { }
+ TaskBase() {}
+ virtual ~TaskBase() {}
};
-template<typename T>
-class Task: public TaskBase {
+template <typename T>
+class Task : public TaskBase {
public:
- Task(): mFuture(new Future<T>()) { }
- virtual ~Task() { }
+ Task() : mFuture(new Future<T>()) {}
+ virtual ~Task() {}
- T getResult() const {
- return mFuture->get();
- }
+ T getResult() const { return mFuture->get(); }
- void setResult(T result) {
- mFuture->produce(result);
- }
+ void setResult(T result) { mFuture->produce(result); }
protected:
- const sp<Future<T> >& future() const {
- return mFuture;
- }
+ const sp<Future<T> >& future() const { return mFuture; }
private:
sp<Future<T> > mFuture;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_TASK_H
+#endif // ANDROID_HWUI_TASK_H
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
index d346b859526e..54b55e472095 100644
--- a/libs/hwui/thread/TaskManager.cpp
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -17,8 +17,8 @@
#include <sys/resource.h>
#include <sys/sysinfo.h>
-#include "TaskManager.h"
#include "Task.h"
+#include "TaskManager.h"
#include "TaskProcessor.h"
#include "utils/MathUtils.h"
@@ -129,5 +129,5 @@ void TaskManager::WorkerThread::exit() {
mSignal.signal();
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h
index c9d12bc6044b..29b4fcdbfde9 100644
--- a/libs/hwui/thread/TaskManager.h
+++ b/libs/hwui/thread/TaskManager.h
@@ -58,7 +58,7 @@ private:
template <typename T>
friend class TaskProcessor;
- template<typename T>
+ template <typename T>
bool addTask(const sp<Task<T> >& task, const sp<TaskProcessor<T> >& processor) {
return addTaskBase(sp<TaskBase>(task), sp<TaskProcessorBase>(processor));
}
@@ -66,19 +66,18 @@ private:
bool addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor);
struct TaskWrapper {
- TaskWrapper(): mTask(), mProcessor() { }
+ TaskWrapper() : mTask(), mProcessor() {}
- TaskWrapper(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor):
- mTask(task), mProcessor(processor) {
- }
+ TaskWrapper(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor)
+ : mTask(task), mProcessor(processor) {}
sp<TaskBase> mTask;
sp<TaskProcessorBase> mProcessor;
};
- class WorkerThread: public Thread {
+ class WorkerThread : public Thread {
public:
- explicit WorkerThread(const String8& name): mSignal(Condition::WAKE_UP_ONE), mName(name) { }
+ explicit WorkerThread(const String8& name) : mSignal(Condition::WAKE_UP_ONE), mName(name) {}
bool addTask(const TaskWrapper& task);
size_t getTaskCount() const;
@@ -102,7 +101,7 @@ private:
std::vector<sp<WorkerThread> > mThreads;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_TASK_MANAGER_H
+#endif // ANDROID_HWUI_TASK_MANAGER_H
diff --git a/libs/hwui/thread/TaskProcessor.h b/libs/hwui/thread/TaskProcessor.h
index 58674505c457..8117ae6409c4 100644
--- a/libs/hwui/thread/TaskProcessor.h
+++ b/libs/hwui/thread/TaskProcessor.h
@@ -25,19 +25,19 @@
namespace android {
namespace uirenderer {
-class TaskProcessorBase: public RefBase {
+class TaskProcessorBase : public RefBase {
public:
- TaskProcessorBase() { }
- virtual ~TaskProcessorBase() { };
+ TaskProcessorBase() {}
+ virtual ~TaskProcessorBase(){};
virtual void process(const sp<TaskBase>& task) = 0;
};
-template<typename T>
-class TaskProcessor: public TaskProcessorBase {
+template <typename T>
+class TaskProcessor : public TaskProcessorBase {
public:
- explicit TaskProcessor(TaskManager* manager): mManager(manager) { }
- virtual ~TaskProcessor() { }
+ explicit TaskProcessor(TaskManager* manager) : mManager(manager) {}
+ virtual ~TaskProcessor() {}
void add(const sp<Task<T> >& task) {
if (!addImpl(task)) {
@@ -52,7 +52,7 @@ private:
bool addImpl(const sp<Task<T> >& task);
virtual void process(const sp<TaskBase>& task) override {
- sp<Task<T> > realTask = static_cast<Task<T>* >(task.get());
+ sp<Task<T> > realTask = static_cast<Task<T>*>(task.get());
// This is the right way to do it but sp<> doesn't play nice
// sp<Task<T> > realTask = static_cast<sp<Task<T> > >(task);
onProcess(realTask);
@@ -61,7 +61,7 @@ private:
TaskManager* mManager;
};
-template<typename T>
+template <typename T>
bool TaskProcessor<T>::addImpl(const sp<Task<T> >& task) {
if (mManager) {
sp<TaskProcessor<T> > self(this);
@@ -70,7 +70,7 @@ bool TaskProcessor<T>::addImpl(const sp<Task<T> >& task) {
return false;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_TASK_PROCESSOR_H
+#endif // ANDROID_HWUI_TASK_PROCESSOR_H
diff --git a/libs/hwui/thread/ThreadBase.h b/libs/hwui/thread/ThreadBase.h
new file mode 100644
index 000000000000..8068121f64cf
--- /dev/null
+++ b/libs/hwui/thread/ThreadBase.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HWUI_THREADBASE_H
+#define HWUI_THREADBASE_H
+
+#include "WorkQueue.h"
+#include "utils/Macros.h"
+
+#include <utils/Looper.h>
+#include <utils/Thread.h>
+
+#include <algorithm>
+
+namespace android::uirenderer {
+
+class ThreadBase : protected Thread {
+ PREVENT_COPY_AND_ASSIGN(ThreadBase);
+
+public:
+ ThreadBase()
+ : Thread(false)
+ , mLooper(new Looper(false))
+ , mQueue([this]() { mLooper->wake(); }, mLock) {}
+
+ WorkQueue& queue() { return mQueue; }
+
+ void requestExit() {
+ Thread::requestExit();
+ mLooper->wake();
+ }
+
+ void start(const char* name = "ThreadBase") { Thread::run(name); }
+
+ void join() { Thread::join(); }
+
+protected:
+ void waitForWork() {
+ nsecs_t nextWakeup;
+ {
+ std::unique_lock lock{mLock};
+ nextWakeup = mQueue.nextWakeup(lock);
+ }
+ int timeout = -1;
+ if (nextWakeup < std::numeric_limits<nsecs_t>::max()) {
+ timeout = ns2ms(nextWakeup - WorkQueue::clock::now());
+ if (timeout < 0) timeout = 0;
+ }
+ int result = mLooper->pollOnce(timeout);
+ LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR, "RenderThread Looper POLL_ERROR!");
+ }
+
+ void processQueue() { mQueue.process(); }
+
+ virtual bool threadLoop() override {
+ while (!exitPending()) {
+ waitForWork();
+ processQueue();
+ }
+ return false;
+ }
+
+ sp<Looper> mLooper;
+
+private:
+ WorkQueue mQueue;
+ std::mutex mLock;
+};
+
+} // namespace android::uirenderer
+
+#endif // HWUI_THREADBASE_H
diff --git a/libs/hwui/thread/WorkQueue.h b/libs/hwui/thread/WorkQueue.h
new file mode 100644
index 000000000000..7a6e638e0568
--- /dev/null
+++ b/libs/hwui/thread/WorkQueue.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HWUI_WORKQUEUE_H
+#define HWUI_WORKQUEUE_H
+
+#include "utils/Macros.h"
+
+#include <log/log.h>
+#include <utils/Timers.h>
+
+#include <condition_variable>
+#include <functional>
+#include <future>
+#include <mutex>
+#include <variant>
+#include <vector>
+
+namespace android::uirenderer {
+
+struct MonotonicClock {
+ static nsecs_t now() { return systemTime(CLOCK_MONOTONIC); }
+};
+
+class WorkQueue {
+ PREVENT_COPY_AND_ASSIGN(WorkQueue);
+
+public:
+ using clock = MonotonicClock;
+
+private:
+ struct WorkItem {
+ WorkItem() = delete;
+ WorkItem(const WorkItem& other) = delete;
+ WorkItem& operator=(const WorkItem& other) = delete;
+ WorkItem(WorkItem&& other) = default;
+ WorkItem& operator=(WorkItem&& other) = default;
+
+ WorkItem(nsecs_t runAt, std::function<void()>&& work)
+ : runAt(runAt), work(std::move(work)) {}
+
+ nsecs_t runAt;
+ std::function<void()> work;
+ };
+
+public:
+ WorkQueue(std::function<void()>&& wakeFunc, std::mutex& lock)
+ : mWakeFunc(move(wakeFunc)), mLock(lock) {}
+
+ void process() {
+ auto now = clock::now();
+ std::vector<WorkItem> toProcess;
+ {
+ std::unique_lock _lock{mLock};
+ if (mWorkQueue.empty()) return;
+ toProcess = std::move(mWorkQueue);
+ auto moveBack = find_if(std::begin(toProcess), std::end(toProcess),
+ [&now](WorkItem& item) { return item.runAt > now; });
+ if (moveBack != std::end(toProcess)) {
+ mWorkQueue.reserve(std::distance(moveBack, std::end(toProcess)) + 5);
+ std::move(moveBack, std::end(toProcess), std::back_inserter(mWorkQueue));
+ toProcess.erase(moveBack, std::end(toProcess));
+ }
+ }
+ for (auto& item : toProcess) {
+ item.work();
+ }
+ }
+
+ template <class F>
+ void postAt(nsecs_t time, F&& func) {
+ enqueue(WorkItem{time, std::function<void()>(std::forward<F>(func))});
+ }
+
+ template <class F>
+ void postDelayed(nsecs_t delay, F&& func) {
+ enqueue(WorkItem{clock::now() + delay, std::function<void()>(std::forward<F>(func))});
+ }
+
+ template <class F>
+ void post(F&& func) {
+ postAt(0, std::forward<F>(func));
+ }
+
+ template <class F>
+ auto async(F&& func) -> std::future<decltype(func())> {
+ typedef std::packaged_task<decltype(func())()> task_t;
+ auto task = std::make_shared<task_t>(std::forward<F>(func));
+ post([task]() { std::invoke(*task); });
+ return task->get_future();
+ }
+
+ template <class F>
+ auto runSync(F&& func) -> decltype(func()) {
+ std::packaged_task<decltype(func())()> task{std::forward<F>(func)};
+ post([&task]() { std::invoke(task); });
+ return task.get_future().get();
+ };
+
+ nsecs_t nextWakeup(std::unique_lock<std::mutex>& lock) {
+ if (mWorkQueue.empty()) {
+ return std::numeric_limits<nsecs_t>::max();
+ } else {
+ return std::begin(mWorkQueue)->runAt;
+ }
+ }
+
+private:
+ void enqueue(WorkItem&& item) {
+ bool needsWakeup;
+ {
+ std::unique_lock _lock{mLock};
+ auto insertAt = std::find_if(
+ std::begin(mWorkQueue), std::end(mWorkQueue),
+ [time = item.runAt](WorkItem & item) { return item.runAt > time; });
+ needsWakeup = std::begin(mWorkQueue) == insertAt;
+ mWorkQueue.emplace(insertAt, std::move(item));
+ }
+ if (needsWakeup) {
+ mWakeFunc();
+ }
+ }
+
+ std::function<void()> mWakeFunc;
+
+ std::mutex& mLock;
+ std::vector<WorkItem> mWorkQueue;
+};
+
+} // namespace android::uirenderer
+
+#endif // HWUI_WORKQUEUE_H
diff --git a/libs/hwui/utils/Blur.cpp b/libs/hwui/utils/Blur.cpp
index 9b70765ee8ad..1bc5646993c9 100644
--- a/libs/hwui/utils/Blur.cpp
+++ b/libs/hwui/utils/Blur.cpp
@@ -38,7 +38,7 @@ float Blur::convertSigmaToRadius(float sigma) {
// is within the conversion error tolerance then we attempt to snap to the
// original integer boundary.
uint32_t Blur::convertRadiusToInt(float radius) {
- const float radiusCeil = ceilf(radius);
+ const float radiusCeil = ceilf(radius);
if (MathUtils::areEqual(radiusCeil, radius)) {
return radiusCeil;
}
@@ -75,46 +75,45 @@ void Blur::generateGaussianWeights(float* weights, float radius) {
// the blur calculations
// precompute some values
float coeff1 = 1.0f / (sqrt(2.0f * pi) * sigma);
- float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+ float coeff2 = -1.0f / (2.0f * sigma * sigma);
float normalizeFactor = 0.0f;
- for (int32_t r = -intRadius; r <= intRadius; r ++) {
- float floatR = (float) r;
+ for (int32_t r = -intRadius; r <= intRadius; r++) {
+ float floatR = (float)r;
weights[r + intRadius] = coeff1 * pow(e, floatR * floatR * coeff2);
normalizeFactor += weights[r + intRadius];
}
- //Now we need to normalize the weights because all our coefficients need to add up to one
+ // Now we need to normalize the weights because all our coefficients need to add up to one
normalizeFactor = 1.0f / normalizeFactor;
- for (int32_t r = -intRadius; r <= intRadius; r ++) {
+ for (int32_t r = -intRadius; r <= intRadius; r++) {
weights[r + intRadius] *= normalizeFactor;
}
}
-void Blur::horizontal(float* weights, int32_t radius,
- const uint8_t* source, uint8_t* dest, int32_t width, int32_t height) {
+void Blur::horizontal(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest,
+ int32_t width, int32_t height) {
float blurredPixel = 0.0f;
float currentPixel = 0.0f;
- for (int32_t y = 0; y < height; y ++) {
-
+ for (int32_t y = 0; y < height; y++) {
const uint8_t* input = source + y * width;
uint8_t* output = dest + y * width;
- for (int32_t x = 0; x < width; x ++) {
+ for (int32_t x = 0; x < width; x++) {
blurredPixel = 0.0f;
const float* gPtr = weights;
// Optimization for non-border pixels
if (x > radius && x < (width - radius)) {
- const uint8_t *i = input + (x - radius);
- for (int r = -radius; r <= radius; r ++) {
- currentPixel = (float) (*i);
+ const uint8_t* i = input + (x - radius);
+ for (int r = -radius; r <= radius; r++) {
+ currentPixel = (float)(*i);
blurredPixel += currentPixel * gPtr[0];
gPtr++;
i++;
}
} else {
- for (int32_t r = -radius; r <= radius; r ++) {
+ for (int32_t r = -radius; r <= radius; r++) {
// Stepping left and right away from the pixel
int validW = x + r;
if (validW < 0) {
@@ -124,40 +123,40 @@ void Blur::horizontal(float* weights, int32_t radius,
validW = width - 1;
}
- currentPixel = (float) input[validW];
+ currentPixel = (float)input[validW];
blurredPixel += currentPixel * gPtr[0];
gPtr++;
}
}
*output = (uint8_t)blurredPixel;
- output ++;
+ output++;
}
}
}
-void Blur::vertical(float* weights, int32_t radius,
- const uint8_t* source, uint8_t* dest, int32_t width, int32_t height) {
+void Blur::vertical(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest,
+ int32_t width, int32_t height) {
float blurredPixel = 0.0f;
float currentPixel = 0.0f;
- for (int32_t y = 0; y < height; y ++) {
+ for (int32_t y = 0; y < height; y++) {
uint8_t* output = dest + y * width;
- for (int32_t x = 0; x < width; x ++) {
+ for (int32_t x = 0; x < width; x++) {
blurredPixel = 0.0f;
const float* gPtr = weights;
const uint8_t* input = source + x;
// Optimization for non-border pixels
if (y > radius && y < (height - radius)) {
- const uint8_t *i = input + ((y - radius) * width);
- for (int32_t r = -radius; r <= radius; r ++) {
- currentPixel = (float) (*i);
+ const uint8_t* i = input + ((y - radius) * width);
+ for (int32_t r = -radius; r <= radius; r++) {
+ currentPixel = (float)(*i);
blurredPixel += currentPixel * gPtr[0];
gPtr++;
i += width;
}
} else {
- for (int32_t r = -radius; r <= radius; r ++) {
+ for (int32_t r = -radius; r <= radius; r++) {
int validH = y + r;
// Clamp to zero and width
if (validH < 0) {
@@ -167,17 +166,17 @@ void Blur::vertical(float* weights, int32_t radius,
validH = height - 1;
}
- const uint8_t *i = input + validH * width;
- currentPixel = (float) (*i);
+ const uint8_t* i = input + validH * width;
+ currentPixel = (float)(*i);
blurredPixel += currentPixel * gPtr[0];
gPtr++;
}
}
- *output = (uint8_t) blurredPixel;
+ *output = (uint8_t)blurredPixel;
output++;
}
}
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/Blur.h b/libs/hwui/utils/Blur.h
index 3f21832bf2b5..bec3837106e8 100644
--- a/libs/hwui/utils/Blur.h
+++ b/libs/hwui/utils/Blur.h
@@ -17,8 +17,8 @@
#ifndef ANDROID_HWUI_BLUR_H
#define ANDROID_HWUI_BLUR_H
-#include <stdint.h>
#include <cutils/compiler.h>
+#include <stdint.h>
namespace android {
namespace uirenderer {
@@ -35,13 +35,13 @@ public:
static uint32_t convertRadiusToInt(float radius);
static void generateGaussianWeights(float* weights, float radius);
- static void horizontal(float* weights, int32_t radius, const uint8_t* source,
- uint8_t* dest, int32_t width, int32_t height);
- static void vertical(float* weights, int32_t radius, const uint8_t* source,
- uint8_t* dest, int32_t width, int32_t height);
+ static void horizontal(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest,
+ int32_t width, int32_t height);
+ static void vertical(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest,
+ int32_t width, int32_t height);
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_HWUI_BLUR_H
+#endif // ANDROID_HWUI_BLUR_H
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 7d234b06b8ca..75740e8b5baf 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -16,6 +16,8 @@
#include "Color.h"
+
+#include <utils/Log.h>
#include <cmath>
namespace android {
@@ -41,18 +43,69 @@ bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace) {
const float sRGBParamG = 2.4f;
// This comparison will catch Display P3
- return
- almostEqual(sRGBParamA, transferFunction.fA)
- && almostEqual(sRGBParamB, transferFunction.fB)
- && almostEqual(sRGBParamC, transferFunction.fC)
- && almostEqual(sRGBParamD, transferFunction.fD)
- && almostEqual(sRGBParamE, transferFunction.fE)
- && almostEqual(sRGBParamF, transferFunction.fF)
- && almostEqual(sRGBParamG, transferFunction.fG);
+ return almostEqual(sRGBParamA, transferFunction.fA) &&
+ almostEqual(sRGBParamB, transferFunction.fB) &&
+ almostEqual(sRGBParamC, transferFunction.fC) &&
+ almostEqual(sRGBParamD, transferFunction.fD) &&
+ almostEqual(sRGBParamE, transferFunction.fE) &&
+ almostEqual(sRGBParamF, transferFunction.fF) &&
+ almostEqual(sRGBParamG, transferFunction.fG);
}
return false;
}
-}; // namespace uirenderer
-}; // namespace android
+sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) {
+
+ SkColorSpace::Gamut gamut;
+ switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ gamut = SkColorSpace::kSRGB_Gamut;
+ break;
+ case HAL_DATASPACE_STANDARD_BT2020:
+ gamut = SkColorSpace::kRec2020_Gamut;
+ break;
+ case HAL_DATASPACE_STANDARD_DCI_P3:
+ gamut = SkColorSpace::kDCIP3_D65_Gamut;
+ break;
+ case HAL_DATASPACE_STANDARD_ADOBE_RGB:
+ gamut = SkColorSpace::kAdobeRGB_Gamut;
+ break;
+ case HAL_DATASPACE_STANDARD_UNSPECIFIED:
+ return nullptr;
+ case HAL_DATASPACE_STANDARD_BT601_625:
+ case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+ case HAL_DATASPACE_STANDARD_BT601_525:
+ case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+ case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+ case HAL_DATASPACE_STANDARD_BT470M:
+ case HAL_DATASPACE_STANDARD_FILM:
+ default:
+ ALOGW("Unsupported Gamut: %d", dataspace);
+ return nullptr;
+ }
+
+ switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_LINEAR:
+ return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, gamut);
+ case HAL_DATASPACE_TRANSFER_SRGB:
+ return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, gamut);
+ case HAL_DATASPACE_TRANSFER_GAMMA2_2:
+ return SkColorSpace::MakeRGB({2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
+ case HAL_DATASPACE_TRANSFER_GAMMA2_6:
+ return SkColorSpace::MakeRGB({2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
+ case HAL_DATASPACE_TRANSFER_GAMMA2_8:
+ return SkColorSpace::MakeRGB({2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
+ case HAL_DATASPACE_TRANSFER_UNSPECIFIED:
+ return nullptr;
+ case HAL_DATASPACE_TRANSFER_SMPTE_170M:
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ case HAL_DATASPACE_TRANSFER_HLG:
+ default:
+ ALOGW("Unsupported Gamma: %d", dataspace);
+ return nullptr;
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 9c096601c826..2bec1f5f7852 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -17,120 +17,103 @@
#define COLOR_H
#include <math.h>
+#include <system/graphics.h>
#include <SkColor.h>
#include <SkColorSpace.h>
namespace android {
namespace uirenderer {
- namespace Color {
- enum Color {
- Red_500 = 0xFFF44336,
- Pink_500 = 0xFFE91E63,
- Purple_500 = 0xFF9C27B0,
- DeepPurple_500 = 0xFF673AB7,
- Indigo_500 = 0xFF3F51B5,
- Blue_500 = 0xFF2196F3,
- LightBlue_300 = 0xFF4FC3F7,
- LightBlue_500 = 0xFF03A9F4,
- Cyan_500 = 0xFF00BCD4,
- Teal_500 = 0xFF009688,
- Teal_700 = 0xFF00796B,
- Green_500 = 0xFF4CAF50,
- Green_700 = 0xFF388E3C,
- LightGreen_500 = 0xFF8BC34A,
- LightGreen_700 = 0xFF689F38,
- Lime_500 = 0xFFCDDC39,
- Yellow_500 = 0xFFFFEB3B,
- Amber_500 = 0xFFFFC107,
- Orange_500 = 0xFFFF9800,
- DeepOrange_500 = 0xFFFF5722,
- Brown_500 = 0xFF795548,
- Grey_200 = 0xFFEEEEEE,
- Grey_500 = 0xFF9E9E9E,
- Grey_700 = 0xFF616161,
- BlueGrey_500 = 0xFF607D8B,
- Transparent = 0x00000000,
- Black = 0xFF000000,
- White = 0xFFFFFFFF,
- };
- }
+namespace Color {
+enum Color {
+ Red_500 = 0xFFF44336,
+ Pink_500 = 0xFFE91E63,
+ Purple_500 = 0xFF9C27B0,
+ DeepPurple_500 = 0xFF673AB7,
+ Indigo_500 = 0xFF3F51B5,
+ Blue_500 = 0xFF2196F3,
+ LightBlue_300 = 0xFF4FC3F7,
+ LightBlue_500 = 0xFF03A9F4,
+ Cyan_500 = 0xFF00BCD4,
+ Teal_500 = 0xFF008577,
+ Teal_700 = 0xFF00796B,
+ Green_500 = 0xFF4CAF50,
+ Green_700 = 0xFF388E3C,
+ LightGreen_500 = 0xFF8BC34A,
+ LightGreen_700 = 0xFF689F38,
+ Lime_500 = 0xFFCDDC39,
+ Yellow_500 = 0xFFFFEB3B,
+ Amber_500 = 0xFFFFC107,
+ Orange_500 = 0xFFFF9800,
+ DeepOrange_500 = 0xFFFF5722,
+ Brown_500 = 0xFF795548,
+ Grey_200 = 0xFFEEEEEE,
+ Grey_500 = 0xFF9E9E9E,
+ Grey_700 = 0xFF616161,
+ BlueGrey_500 = 0xFF607D8B,
+ Transparent = 0x00000000,
+ Black = 0xFF000000,
+ White = 0xFFFFFFFF,
+};
+}
- static_assert(Color::White == SK_ColorWHITE, "color format has changed");
- static_assert(Color::Black == SK_ColorBLACK, "color format has changed");
+static_assert(Color::White == SK_ColorWHITE, "color format has changed");
+static_assert(Color::Black == SK_ColorBLACK, "color format has changed");
- // Array of bright (500 intensity) colors for synthetic content
- static const Color::Color BrightColors[] = {
- Color::Red_500,
- Color::Pink_500,
- Color::Purple_500,
- Color::DeepPurple_500,
- Color::Indigo_500,
- Color::Blue_500,
- Color::LightBlue_500,
- Color::Cyan_500,
- Color::Teal_500,
- Color::Green_500,
- Color::LightGreen_500,
- Color::Lime_500,
- Color::Yellow_500,
- Color::Amber_500,
- Color::Orange_500,
- Color::DeepOrange_500,
- Color::Brown_500,
- Color::Grey_500,
- Color::BlueGrey_500,
- };
- static constexpr int BrightColorsCount = sizeof(BrightColors) / sizeof(Color::Color);
+// Array of bright (500 intensity) colors for synthetic content
+static const Color::Color BrightColors[] = {
+ Color::Red_500, Color::Pink_500, Color::Purple_500, Color::DeepPurple_500,
+ Color::Indigo_500, Color::Blue_500, Color::LightBlue_500, Color::Cyan_500,
+ Color::Teal_500, Color::Green_500, Color::LightGreen_500, Color::Lime_500,
+ Color::Yellow_500, Color::Amber_500, Color::Orange_500, Color::DeepOrange_500,
+ Color::Brown_500, Color::Grey_500, Color::BlueGrey_500,
+};
+static constexpr int BrightColorsCount = sizeof(BrightColors) / sizeof(Color::Color);
- enum class TransferFunctionType : int8_t {
- None = 0,
- Full,
- Limited,
- Gamma
- };
+enum class TransferFunctionType : int8_t { None = 0, Full, Limited, Gamma };
- // Opto-electronic conversion function for the sRGB color space
- // Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
- static constexpr float OECF_sRGB(float linear) {
- // IEC 61966-2-1:1999
- return linear <= 0.0031308f ?
- linear * 12.92f : (powf(linear, 1.0f / 2.4f) * 1.055f) - 0.055f;
- }
+// Opto-electronic conversion function for the sRGB color space
+// Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
+static constexpr float OECF_sRGB(float linear) {
+ // IEC 61966-2-1:1999
+ return linear <= 0.0031308f ? linear * 12.92f : (powf(linear, 1.0f / 2.4f) * 1.055f) - 0.055f;
+}
- // Opto-electronic conversion function for the sRGB color space
- // Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
- // This function returns the input unmodified if linear blending is not enabled
- static constexpr float OECF(float linear) {
+// Opto-electronic conversion function for the sRGB color space
+// Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
+// This function returns the input unmodified if linear blending is not enabled
+static constexpr float OECF(float linear) {
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
- return OECF_sRGB(linear);
+ return OECF_sRGB(linear);
#else
- return linear;
+ return linear;
#endif
- }
+}
- // Electro-optical conversion function for the sRGB color space
- // Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
- static constexpr float EOCF_sRGB(float srgb) {
- // IEC 61966-2-1:1999
- return srgb <= 0.04045f ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
- }
+// Electro-optical conversion function for the sRGB color space
+// Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
+static constexpr float EOCF_sRGB(float srgb) {
+ // IEC 61966-2-1:1999
+ return srgb <= 0.04045f ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
+}
- // Electro-optical conversion function for the sRGB color space
- // Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
- // This function returns the input unmodified if linear blending is not enabled
- static constexpr float EOCF(float srgb) {
+// Electro-optical conversion function for the sRGB color space
+// Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
+// This function returns the input unmodified if linear blending is not enabled
+static constexpr float EOCF(float srgb) {
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
- return EOCF_sRGB(srgb);
+ return EOCF_sRGB(srgb);
#else
- return srgb;
+ return srgb;
#endif
- }
+}
- // Returns whether the specified color space's transfer function can be
- // approximated with the native sRGB transfer function. This method
- // returns true for sRGB, gamma 2.2 and Display P3 for instance
- bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace);
+// Returns whether the specified color space's transfer function can be
+// approximated with the native sRGB transfer function. This method
+// returns true for sRGB, gamma 2.2 and Display P3 for instance
+bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace);
+
+sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/utils/FatVector.h b/libs/hwui/utils/FatVector.h
index df8cb076e763..eafe2f13c16d 100644
--- a/libs/hwui/utils/FatVector.h
+++ b/libs/hwui/utils/FatVector.h
@@ -30,8 +30,8 @@
#include <stddef.h>
#include <stdlib.h>
-#include <type_traits>
#include <utils/Log.h>
+#include <type_traits>
#include <vector>
@@ -43,28 +43,27 @@ class InlineStdAllocator {
public:
struct Allocation {
PREVENT_COPY_AND_ASSIGN(Allocation);
+
public:
- Allocation() {};
+ Allocation(){};
// char array instead of T array, so memory is uninitialized, with no destructors run
char array[sizeof(T) * SIZE];
bool inUse = false;
};
- typedef T value_type; // needed to implement std::allocator
- typedef T* pointer; // needed to implement std::allocator
+ typedef T value_type; // needed to implement std::allocator
+ typedef T* pointer; // needed to implement std::allocator
- explicit InlineStdAllocator(Allocation& allocation)
- : mAllocation(allocation) {}
- InlineStdAllocator(const InlineStdAllocator& other)
- : mAllocation(other.mAllocation) {}
+ explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
+ InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
~InlineStdAllocator() {}
T* allocate(size_t num, const void* = 0) {
if (!mAllocation.inUse && num <= SIZE) {
mAllocation.inUse = true;
- return (T*) mAllocation.array;
+ return (T*)mAllocation.array;
} else {
- return (T*) malloc(num * sizeof(T));
+ return (T*)malloc(num * sizeof(T));
}
}
@@ -88,20 +87,19 @@ public:
template <typename T, size_t SIZE>
class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
public:
- FatVector() : std::vector<T, InlineStdAllocator<T, SIZE>>(
- InlineStdAllocator<T, SIZE>(mAllocation)) {
+ FatVector()
+ : std::vector<T, InlineStdAllocator<T, SIZE>>(
+ InlineStdAllocator<T, SIZE>(mAllocation)) {
this->reserve(SIZE);
}
- explicit FatVector(size_t capacity) : FatVector() {
- this->resize(capacity);
- }
+ explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
private:
typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_FAT_VECTOR_H
+#endif // ANDROID_FAT_VECTOR_H
diff --git a/libs/hwui/utils/GLUtils.cpp b/libs/hwui/utils/GLUtils.cpp
index 332097593c86..bf27300029c6 100644
--- a/libs/hwui/utils/GLUtils.cpp
+++ b/libs/hwui/utils/GLUtils.cpp
@@ -39,25 +39,25 @@ bool GLUtils::dumpGLErrors() {
while ((status = glGetError()) != GL_NO_ERROR) {
errorObserved = true;
switch (status) {
- case GL_INVALID_ENUM:
- ALOGE("GL error: GL_INVALID_ENUM");
- break;
- case GL_INVALID_VALUE:
- ALOGE("GL error: GL_INVALID_VALUE");
- break;
- case GL_INVALID_OPERATION:
- ALOGE("GL error: GL_INVALID_OPERATION");
- break;
- case GL_OUT_OF_MEMORY:
- ALOGE("GL error: Out of memory!");
- break;
- default:
- ALOGE("GL error: 0x%x", status);
+ case GL_INVALID_ENUM:
+ ALOGE("GL error: GL_INVALID_ENUM");
+ break;
+ case GL_INVALID_VALUE:
+ ALOGE("GL error: GL_INVALID_VALUE");
+ break;
+ case GL_INVALID_OPERATION:
+ ALOGE("GL error: GL_INVALID_OPERATION");
+ break;
+ case GL_OUT_OF_MEMORY:
+ ALOGE("GL error: Out of memory!");
+ break;
+ default:
+ ALOGE("GL error: 0x%x", status);
}
}
return errorObserved;
#endif
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h
index c12747805293..debfb5d06944 100644
--- a/libs/hwui/utils/GLUtils.h
+++ b/libs/hwui/utils/GLUtils.h
@@ -23,13 +23,14 @@
namespace android {
namespace uirenderer {
-
#if DEBUG_OPENGL
-#define GL_CHECKPOINT(LEVEL) \
- do { if (DEBUG_OPENGL >= DEBUG_LEVEL_##LEVEL) {\
- LOG_ALWAYS_FATAL_IF(android::uirenderer::GLUtils::dumpGLErrors(),\
- "GL errors! %s:%d", __FILE__, __LINE__);\
- } } while (0)
+#define GL_CHECKPOINT(LEVEL) \
+ do { \
+ if (DEBUG_OPENGL >= DEBUG_LEVEL_##LEVEL) { \
+ LOG_ALWAYS_FATAL_IF(android::uirenderer::GLUtils::dumpGLErrors(), "GL errors! %s:%d", \
+ __FILE__, __LINE__); \
+ } \
+ } while (0)
#else
#define GL_CHECKPOINT(LEVEL)
#endif
@@ -42,7 +43,7 @@ public:
*/
static bool dumpGLErrors();
-}; // class GLUtils
+}; // class GLUtils
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/utils/LinearAllocator.cpp b/libs/hwui/utils/LinearAllocator.cpp
index d92bc0cd1fca..5a59de8b922a 100644
--- a/libs/hwui/utils/LinearAllocator.cpp
+++ b/libs/hwui/utils/LinearAllocator.cpp
@@ -30,10 +30,9 @@
#include <stdlib.h>
#include <utils/Log.h>
-
// The ideal size of a page allocation (these need to be multiples of 8)
-#define INITIAL_PAGE_SIZE ((size_t)512) // 512b
-#define MAX_PAGE_SIZE ((size_t)131072) // 128kb
+#define INITIAL_PAGE_SIZE ((size_t)512) // 512b
+#define MAX_PAGE_SIZE ((size_t)131072) // 128kb
// The maximum amount of wasted space we can have per page
// Allocations exceeding this will have their own dedicated page
@@ -48,7 +47,7 @@
#define ALIGN_SZ (sizeof(int))
#endif
-#define ALIGN(x) (((x) + ALIGN_SZ - 1 ) & ~(ALIGN_SZ - 1))
+#define ALIGN(x) (((x) + ALIGN_SZ - 1) & ~(ALIGN_SZ - 1))
#define ALIGN_PTR(p) ((void*)(ALIGN((size_t)(p))))
#if LOG_NDEBUG
@@ -79,7 +78,7 @@ static void _addAllocation(int count) {
#define RM_ALLOCATION(size) _addAllocation(-1);
#endif
-#define min(x,y) (((x) < (y)) ? (x) : (y))
+#define min(x, y) (((x) < (y)) ? (x) : (y))
namespace android {
namespace uirenderer {
@@ -89,19 +88,13 @@ public:
Page* next() { return mNextPage; }
void setNext(Page* next) { mNextPage = next; }
- Page()
- : mNextPage(0)
- {}
+ Page() : mNextPage(0) {}
void* operator new(size_t /*size*/, void* buf) { return buf; }
- void* start() {
- return (void*) (((size_t)this) + sizeof(Page));
- }
+ void* start() { return (void*)(((size_t)this) + sizeof(Page)); }
- void* end(int pageSize) {
- return (void*) (((size_t)start()) + pageSize);
- }
+ void* end(int pageSize) { return (void*)(((size_t)start()) + pageSize); }
private:
Page(const Page& /*other*/) {}
@@ -109,15 +102,15 @@ private:
};
LinearAllocator::LinearAllocator()
- : mPageSize(INITIAL_PAGE_SIZE)
- , mMaxAllocSize(INITIAL_PAGE_SIZE * MAX_WASTE_RATIO)
- , mNext(0)
- , mCurrentPage(0)
- , mPages(0)
- , mTotalAllocated(0)
- , mWastedSpace(0)
- , mPageCount(0)
- , mDedicatedPageCount(0) {}
+ : mPageSize(INITIAL_PAGE_SIZE)
+ , mMaxAllocSize(INITIAL_PAGE_SIZE * MAX_WASTE_RATIO)
+ , mNext(0)
+ , mCurrentPage(0)
+ , mPages(0)
+ , mTotalAllocated(0)
+ , mWastedSpace(0)
+ , mPageCount(0)
+ , mDedicatedPageCount(0) {}
LinearAllocator::~LinearAllocator(void) {
while (mDtorList) {
@@ -176,8 +169,7 @@ void* LinearAllocator::allocImpl(size_t size) {
mDedicatedPageCount++;
page->setNext(mPages);
mPages = page;
- if (!mCurrentPage)
- mCurrentPage = mPages;
+ if (!mCurrentPage) mCurrentPage = mPages;
return start(page);
}
ensureNext(size);
@@ -225,8 +217,8 @@ void LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize) {
runDestructorFor(ptr);
// Don't bother rewinding across pages
allocSize = ALIGN(allocSize);
- if (ptr >= start(mCurrentPage) && ptr < end(mCurrentPage)
- && ptr == ((char*)mNext - allocSize)) {
+ if (ptr >= start(mCurrentPage) && ptr < end(mCurrentPage) &&
+ ptr == ((char*)mNext - allocSize)) {
mWastedSpace += allocSize;
mNext = ptr;
}
@@ -261,9 +253,9 @@ void LinearAllocator::dumpMemoryStats(const char* prefix) {
ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix);
prettySuffix = toSize(mWastedSpace, prettySize);
ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix,
- (float) mWastedSpace / (float) mTotalAllocated * 100.0f);
+ (float)mWastedSpace / (float)mTotalAllocated * 100.0f);
ALOGD("%sPages %zu (dedicated %zu)", prefix, mPageCount, mDedicatedPageCount);
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index f95a6fe5060e..03f685e8aca8 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -56,10 +56,10 @@ public:
* Note that unlike create, for alloc the type is purely for compile-time error
* checking and does not affect size.
*/
- template<class T>
+ template <class T>
void* alloc(size_t size) {
static_assert(std::is_trivially_destructible<T>::value,
- "Error, type is non-trivial! did you mean to use create()?");
+ "Error, type is non-trivial! did you mean to use create()?");
return allocImpl(size);
}
@@ -67,7 +67,7 @@ public:
* Allocates an instance of the template type with the given construction parameters
* and adds it to the automatic destruction list.
*/
- template<class T, typename... Params>
+ template <class T, typename... Params>
T* create(Params&&... params) {
T* ret = new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...);
if (!std::is_trivially_destructible<T>::value) {
@@ -77,17 +77,17 @@ public:
return ret;
}
- template<class T, typename... Params>
+ template <class T, typename... Params>
T* create_trivial(Params&&... params) {
static_assert(std::is_trivially_destructible<T>::value,
- "Error, called create_trivial on a non-trivial type");
+ "Error, called create_trivial on a non-trivial type");
return new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...);
}
- template<class T>
+ template <class T>
T* create_trivial_array(int count) {
static_assert(std::is_trivially_destructible<T>::value,
- "Error, called create_trivial_array on a non-trivial type");
+ "Error, called create_trivial_array on a non-trivial type");
return reinterpret_cast<T*>(allocImpl(sizeof(T) * count));
}
@@ -100,7 +100,7 @@ public:
/**
* Same as rewindIfLastAlloc(void*, size_t)
*/
- template<class T>
+ template <class T>
void rewindIfLastAlloc(T* ptr) {
rewindIfLastAlloc((void*)ptr, sizeof(T));
}
@@ -134,7 +134,7 @@ private:
Page* newPage(size_t pageSize);
bool fitsInCurrentPage(size_t size);
void ensureNext(size_t size);
- void* start(Page *p);
+ void* start(Page* p);
void* end(Page* p);
size_t mPageSize;
@@ -154,13 +154,11 @@ private:
template <class T>
class LinearStdAllocator {
public:
- typedef T value_type; // needed to implement std::allocator
- typedef T* pointer; // needed to implement std::allocator
+ typedef T value_type; // needed to implement std::allocator
+ typedef T* pointer; // needed to implement std::allocator
- explicit LinearStdAllocator(LinearAllocator& allocator)
- : linearAllocator(allocator) {}
- LinearStdAllocator(const LinearStdAllocator& other)
- : linearAllocator(other.linearAllocator) {}
+ explicit LinearStdAllocator(LinearAllocator& allocator) : linearAllocator(allocator) {}
+ LinearStdAllocator(const LinearStdAllocator& other) : linearAllocator(other.linearAllocator) {}
~LinearStdAllocator() {}
// rebind marks that allocators can be rebound to different types
@@ -188,9 +186,13 @@ public:
// return that all specializations of LinearStdAllocator are interchangeable
template <class T1, class T2>
-bool operator== (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return true; }
+bool operator==(const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) {
+ return true;
+}
template <class T1, class T2>
-bool operator!= (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return false; }
+bool operator!=(const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) {
+ return false;
+}
template <class T>
class LsaVector : public std::vector<T, LinearStdAllocator<T>> {
@@ -199,7 +201,7 @@ public:
: std::vector<T, LinearStdAllocator<T>>(allocator) {}
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
-#endif // ANDROID_LINEARALLOCATOR_H
+#endif // ANDROID_LINEARALLOCATOR_H
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index 7212897bf5d3..d758f29d6dcb 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -19,21 +19,19 @@
#include <type_traits>
#define PREVENT_COPY_AND_ASSIGN(Type) \
- private: \
- Type(const Type&) = delete; \
- void operator=(const Type&) = delete
+private: \
+ Type(const Type&) = delete; \
+ void operator=(const Type&) = delete
-#define HASHABLE_TYPE(Type) \
- bool operator==(const Type& other) const; \
- hash_t hash() const; \
- bool operator!=(const Type& other) const { return !(*this == other); } \
- friend inline hash_t hash_type(const Type& entry) { return entry.hash(); }
+#define HASHABLE_TYPE(Type) \
+ bool operator==(const Type& other) const; \
+ hash_t hash() const; \
+ bool operator!=(const Type& other) const { return !(*this == other); } \
+ friend inline hash_t hash_type(const Type& entry) { return entry.hash(); }
#define REQUIRE_COMPATIBLE_LAYOUT(Type) \
- static_assert(std::is_standard_layout<Type>::value, \
- #Type " must have standard layout")
+ static_assert(std::is_standard_layout<Type>::value, #Type " must have standard layout")
-#define WARN_UNUSED_RESULT \
- __attribute__((warn_unused_result))
+#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#endif /* MACROS_H */
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 8d20f2142e73..5475898bff28 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -16,8 +16,8 @@
#ifndef MATHUTILS_H
#define MATHUTILS_H
-#include <algorithm>
#include <math.h>
+#include <algorithm>
namespace android {
namespace uirenderer {
@@ -34,9 +34,7 @@ public:
return (value >= -NON_ZERO_EPSILON) && (value <= NON_ZERO_EPSILON);
}
- inline static bool isPositive(float value) {
- return value >= NON_ZERO_EPSILON;
- }
+ inline static bool isPositive(float value) { return value >= NON_ZERO_EPSILON; }
/**
* Clamps alpha value, and snaps when very near 0 or 1
@@ -69,28 +67,24 @@ public:
* Returns the number of points (beyond two, the start and end) needed to form a polygonal
* approximation of an arc, with a given threshold value.
*/
- inline static int divisionsNeededToApproximateArc(float radius,
- float angleInRads, float threshold) {
+ inline static int divisionsNeededToApproximateArc(float radius, float angleInRads,
+ float threshold) {
const float errConst = (-threshold / radius + 1);
const float targetCosVal = 2 * errConst * errConst - 1;
// needed divisions are rounded up from approximation
- return (int)(ceilf(angleInRads / acos(targetCosVal)/2)) * 2;
+ return (int)(ceilf(angleInRads / acos(targetCosVal) / 2)) * 2;
}
- inline static bool areEqual(float valueA, float valueB) {
- return isZero(valueA - valueB);
- }
+ inline static bool areEqual(float valueA, float valueB) { return isZero(valueA - valueB); }
- template<typename T>
+ template <typename T>
static inline T clamp(T a, T minValue, T maxValue) {
return std::min(std::max(a, minValue), maxValue);
}
- inline static float lerp(float v1, float v2, float t) {
- return v1 + ((v2 - v1) * t);
- }
-}; // class MathUtils
+ inline static float lerp(float v1, float v2, float t) { return v1 + ((v2 - v1) * t); }
+}; // class MathUtils
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 2673be1cb6fa..233adae1df24 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -31,7 +31,6 @@ namespace uirenderer {
*/
class PaintUtils {
public:
-
static inline GLenum getFilter(const SkPaint* paint) {
if (!paint || paint->getFilterQuality() != kNone_SkFilterQuality) {
return GL_LINEAR;
@@ -40,18 +39,16 @@ public:
}
static bool isOpaquePaint(const SkPaint* paint) {
- if (!paint) return true; // default (paintless) behavior is SrcOver, black
+ if (!paint) return true; // default (paintless) behavior is SrcOver, black
- if (paint->getAlpha() != 0xFF
- || PaintUtils::isBlendedShader(paint->getShader())
- || PaintUtils::isBlendedColorFilter(paint->getColorFilter())) {
+ if (paint->getAlpha() != 0xFF || PaintUtils::isBlendedShader(paint->getShader()) ||
+ PaintUtils::isBlendedColorFilter(paint->getColorFilter())) {
return false;
}
// Only let simple srcOver / src blending modes declare opaque, since behavior is clear.
SkBlendMode mode = paint->getBlendMode();
- return mode == SkBlendMode::kSrcOver
- || mode == SkBlendMode::kSrc;
+ return mode == SkBlendMode::kSrcOver || mode == SkBlendMode::kSrc;
}
static bool isBlendedShader(const SkShader* shader) {
@@ -89,9 +86,7 @@ public:
return false;
}
- static inline bool hasTextShadow(const SkPaint* paint) {
- return getTextShadow(paint, nullptr);
- }
+ static inline bool hasTextShadow(const SkPaint* paint) { return getTextShadow(paint, nullptr); }
static inline SkBlendMode getBlendModeDirect(const SkPaint* paint) {
return paint ? paint->getBlendMode() : SkBlendMode::kSrcOver;
@@ -101,7 +96,7 @@ public:
return paint ? paint->getAlpha() : 255;
}
-}; // class PaintUtils
+}; // class PaintUtils
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/utils/Pair.h b/libs/hwui/utils/Pair.h
index 0db3aa38d8b1..4bcd57629e0c 100644
--- a/libs/hwui/utils/Pair.h
+++ b/libs/hwui/utils/Pair.h
@@ -27,34 +27,34 @@ struct Pair {
F first;
S second;
- Pair() { }
- Pair(const Pair& o) : first(o.first), second(o.second) { }
- Pair(const F& f, const S& s) : first(f), second(s) { }
+ Pair() {}
+ Pair(const Pair& o) : first(o.first), second(o.second) {}
+ Pair(const F& f, const S& s) : first(f), second(s) {}
- inline const F& getFirst() const {
- return first;
- }
+ inline const F& getFirst() const { return first; }
- inline const S& getSecond() const {
- return second;
- }
+ inline const S& getSecond() const { return second; }
};
-}; // namespace uirenderer
+}; // namespace uirenderer
template <typename F, typename S>
-struct trait_trivial_ctor< uirenderer::Pair<F, S> >
-{ enum { value = aggregate_traits<F, S>::has_trivial_ctor }; };
+struct trait_trivial_ctor<uirenderer::Pair<F, S> > {
+ enum { value = aggregate_traits<F, S>::has_trivial_ctor };
+};
template <typename F, typename S>
-struct trait_trivial_dtor< uirenderer::Pair<F, S> >
-{ enum { value = aggregate_traits<F, S>::has_trivial_dtor }; };
+struct trait_trivial_dtor<uirenderer::Pair<F, S> > {
+ enum { value = aggregate_traits<F, S>::has_trivial_dtor };
+};
template <typename F, typename S>
-struct trait_trivial_copy< uirenderer::Pair<F, S> >
-{ enum { value = aggregate_traits<F, S>::has_trivial_copy }; };
+struct trait_trivial_copy<uirenderer::Pair<F, S> > {
+ enum { value = aggregate_traits<F, S>::has_trivial_copy };
+};
template <typename F, typename S>
-struct trait_trivial_move< uirenderer::Pair<F, S> >
-{ enum { value = aggregate_traits<F, S>::has_trivial_move }; };
+struct trait_trivial_move<uirenderer::Pair<F, S> > {
+ enum { value = aggregate_traits<F, S>::has_trivial_move };
+};
-}; // namespace android
+}; // namespace android
-#endif // ANDROID_HWUI_PAIR_H
+#endif // ANDROID_HWUI_PAIR_H
diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h
index 06bcdcd7d84b..b3e893139cf8 100644
--- a/libs/hwui/utils/RingBuffer.h
+++ b/libs/hwui/utils/RingBuffer.h
@@ -23,7 +23,7 @@
namespace android {
namespace uirenderer {
-template<class T, size_t SIZE>
+template <class T, size_t SIZE>
class RingBuffer {
PREVENT_COPY_AND_ASSIGN(RingBuffer);
@@ -42,21 +42,13 @@ public:
return mBuffer[mHead];
}
- T& front() {
- return (*this)[0];
- }
+ T& front() { return (*this)[0]; }
- T& back() {
- return (*this)[size() - 1];
- }
+ T& back() { return (*this)[size() - 1]; }
- T& operator[](size_t index) {
- return mBuffer[(mHead + index + 1) % mCount];
- }
+ T& operator[](size_t index) { return mBuffer[(mHead + index + 1) % mCount]; }
- const T& operator[](size_t index) const {
- return mBuffer[(mHead + index + 1) % mCount];
- }
+ const T& operator[](size_t index) const { return mBuffer[(mHead + index + 1) % mCount]; }
void clear() {
mCount = 0;
@@ -69,7 +61,7 @@ private:
size_t mCount = 0;
};
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
#endif /* RINGBUFFER_H_ */
diff --git a/libs/hwui/utils/StringUtils.cpp b/libs/hwui/utils/StringUtils.cpp
index 64a59705028a..5304b762f3dc 100644
--- a/libs/hwui/utils/StringUtils.cpp
+++ b/libs/hwui/utils/StringUtils.cpp
@@ -34,5 +34,5 @@ unordered_string_set StringUtils::split(const char* spacedList) {
return set;
}
-}; // namespace uirenderer
-}; // namespace android
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/StringUtils.h b/libs/hwui/utils/StringUtils.h
index af5d10f8522b..a10610a3d0da 100644
--- a/libs/hwui/utils/StringUtils.h
+++ b/libs/hwui/utils/StringUtils.h
@@ -30,9 +30,7 @@ namespace uirenderer {
class unordered_string_set : public std::unordered_set<std::string> {
public:
- bool has(const char* str) {
- return find(std::string(str)) != end();
- }
+ bool has(const char* str) { return find(std::string(str)) != end(); }
};
class StringUtils {
@@ -55,8 +53,8 @@ struct SizePrinter {
}
};
-class LogcatStream: public std::ostream {
- class LogcatStreamBuf: public std::stringbuf {
+class LogcatStream : public std::ostream {
+ class LogcatStreamBuf : public std::stringbuf {
virtual int sync() {
ALOGD("%s", str().c_str());
str("");
@@ -65,10 +63,9 @@ class LogcatStream: public std::ostream {
};
LogcatStreamBuf buffer;
+
public:
- LogcatStream()
- :std::ostream(&buffer) {
- }
+ LogcatStream() : std::ostream(&buffer) {}
};
} /* namespace uirenderer */
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index 492ca7fe62fa..700d3b3cf000 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -36,13 +36,13 @@ namespace {
*/
class ContextFactory : public android::uirenderer::IContextFactory {
public:
- android::uirenderer::AnimationContext* createAnimationContext
- (android::uirenderer::renderthread::TimeLord& clock) override {
+ android::uirenderer::AnimationContext* createAnimationContext(
+ android::uirenderer::renderthread::TimeLord& clock) override {
return new android::uirenderer::AnimationContext(clock);
}
};
-} // anonymous namespace
+} // anonymous namespace
namespace android {
namespace uirenderer {
@@ -54,45 +54,38 @@ namespace uirenderer {
*/
class TestWindowContext::TestWindowData {
-
public:
-
explicit TestWindowData(SkISize size) : mSize(size) {
android::BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mCpuConsumer = new android::CpuConsumer(mConsumer, 1);
mCpuConsumer->setName(android::String8("TestWindowContext"));
mCpuConsumer->setDefaultBufferSize(mSize.width(), mSize.height());
mAndroidSurface = new android::Surface(mProducer);
- native_window_set_buffers_dimensions(mAndroidSurface.get(),
- mSize.width(), mSize.height());
- native_window_set_buffers_format(mAndroidSurface.get(),
- android::PIXEL_FORMAT_RGBA_8888);
- native_window_set_usage(mAndroidSurface.get(),
- GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_NEVER |
- GRALLOC_USAGE_HW_RENDER);
+ native_window_set_buffers_dimensions(mAndroidSurface.get(), mSize.width(), mSize.height());
+ native_window_set_buffers_format(mAndroidSurface.get(), android::PIXEL_FORMAT_RGBA_8888);
+ native_window_set_usage(mAndroidSurface.get(), GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_NEVER |
+ GRALLOC_USAGE_HW_RENDER);
mRootNode.reset(new android::uirenderer::RenderNode());
mRootNode->incStrong(nullptr);
- mRootNode->mutateStagingProperties().setLeftTopRightBottom
- (0, 0, mSize.width(), mSize.height());
+ mRootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, mSize.width(),
+ mSize.height());
mRootNode->mutateStagingProperties().setClipToBounds(false);
mRootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);
ContextFactory factory;
- mProxy.reset
- (new android::uirenderer::renderthread::RenderProxy(false,
- mRootNode.get(),
- &factory));
+ mProxy.reset(new android::uirenderer::renderthread::RenderProxy(false, mRootNode.get(),
+ &factory));
mProxy->loadSystemProperties();
mProxy->initialize(mAndroidSurface.get());
float lightX = mSize.width() / 2.0f;
- android::uirenderer::Vector3 lightVector { lightX, -200.0f, 800.0f };
+ android::uirenderer::Vector3 lightVector{lightX, -200.0f, 800.0f};
mProxy->setup(800.0f, 255 * 0.075f, 255 * 0.15f);
mProxy->setLightCenter(lightVector);
mCanvas.reset(new android::uirenderer::RecordingCanvas(mSize.width(), mSize.height()));
}
SkCanvas* prepareToDraw() {
- //mCanvas->reset(mSize.width(), mSize.height());
+ // mCanvas->reset(mSize.width(), mSize.height());
mCanvas->clipRect(0, 0, mSize.width(), mSize.height(), SkClipOp::kReplace_deprecated);
return mCanvas->asSkCanvas();
}
@@ -104,17 +97,15 @@ public:
// the timings we record.
}
- void fence() {
- mProxy->fence();
- }
+ void fence() { mProxy->fence(); }
bool capturePixels(SkBitmap* bmp) {
sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
SkImageInfo destinationConfig =
- SkImageInfo::Make(mSize.width(), mSize.height(),
- kRGBA_8888_SkColorType, kPremul_SkAlphaType, colorSpace);
+ SkImageInfo::Make(mSize.width(), mSize.height(), kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType, colorSpace);
bmp->allocPixels(destinationConfig);
- android_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
+ android_memset32((uint32_t*)bmp->getPixels(), SK_ColorRED,
mSize.width() * mSize.height() * 4);
android::CpuConsumer::LockedBuffer nativeBuffer;
@@ -135,14 +126,13 @@ public:
LOG_ALWAYS_FATAL_IF(nativeBuffer.format != android::PIXEL_FORMAT_RGBA_8888,
"Native buffer not RGBA!");
- SkImageInfo nativeConfig =
- SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
- kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ SkImageInfo nativeConfig = SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType);
// Android stride is in pixels, Skia stride is in bytes
SkBitmap nativeWrapper;
- bool success =
- nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4);
+ bool success = nativeWrapper.installPixels(nativeConfig, nativeBuffer.data,
+ nativeBuffer.stride * 4);
if (!success) {
SkDebugf("Failed to wrap HWUI buffer in a SkBitmap");
return false;
@@ -150,8 +140,8 @@ public:
LOG_ALWAYS_FATAL_IF(bmp->colorType() != kRGBA_8888_SkColorType,
"Destination buffer not RGBA!");
- success =
- nativeWrapper.readPixels(destinationConfig, bmp->getPixels(), bmp->rowBytes(), 0, 0);
+ success = nativeWrapper.readPixels(destinationConfig, bmp->getPixels(), bmp->rowBytes(), 0,
+ 0);
if (!success) {
SkDebugf("Failed to extract pixels from HWUI buffer");
return false;
@@ -163,7 +153,6 @@ public:
}
private:
-
std::unique_ptr<android::uirenderer::RenderNode> mRootNode;
std::unique_ptr<android::uirenderer::renderthread::RenderProxy> mProxy;
std::unique_ptr<android::uirenderer::RecordingCanvas> mCanvas;
@@ -174,15 +163,13 @@ private:
SkISize mSize;
};
-
-TestWindowContext::TestWindowContext() :
- mData (nullptr) { }
+TestWindowContext::TestWindowContext() : mData(nullptr) {}
TestWindowContext::~TestWindowContext() {
delete mData;
}
-void TestWindowContext::initialize(int width, int height) {
+void TestWindowContext::initialize(int width, int height) {
mData = new TestWindowData(SkISize::Make(width, height));
}
@@ -206,6 +193,5 @@ bool TestWindowContext::capturePixels(SkBitmap* bmp) {
return mData ? mData->capturePixels(bmp) : false;
}
-} // namespace uirenderer
-} // namespace android
-
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/utils/TestWindowContext.h b/libs/hwui/utils/TestWindowContext.h
index 48ec95216b14..17ad1e3fef55 100644
--- a/libs/hwui/utils/TestWindowContext.h
+++ b/libs/hwui/utils/TestWindowContext.h
@@ -31,9 +31,7 @@ namespace uirenderer {
*/
class ANDROID_API TestWindowContext {
-
public:
-
TestWindowContext();
~TestWindowContext();
@@ -58,11 +56,9 @@ private:
class TestWindowData;
TestWindowData* mData;
-
};
} // namespace uirenderer
} // namespace android
#endif // TESTWINDOWCONTEXT_H_
-
diff --git a/libs/hwui/utils/TimeUtils.h b/libs/hwui/utils/TimeUtils.h
index ce181b766841..f66edeaa2a4e 100644
--- a/libs/hwui/utils/TimeUtils.h
+++ b/libs/hwui/utils/TimeUtils.h
@@ -21,15 +21,15 @@
namespace android {
namespace uirenderer {
-constexpr nsecs_t operator"" _s (unsigned long long s) {
+constexpr nsecs_t operator"" _s(unsigned long long s) {
return seconds_to_nanoseconds(s);
}
-constexpr nsecs_t operator"" _ms (unsigned long long ms) {
+constexpr nsecs_t operator"" _ms(unsigned long long ms) {
return milliseconds_to_nanoseconds(ms);
}
-constexpr nsecs_t operator"" _us (unsigned long long us) {
+constexpr nsecs_t operator"" _us(unsigned long long us) {
return microseconds_to_nanoseconds(us);
}
diff --git a/libs/hwui/utils/Timing.h b/libs/hwui/utils/Timing.h
index 4b1fabe42c35..978c7bcf7a57 100644
--- a/libs/hwui/utils/Timing.h
+++ b/libs/hwui/utils/Timing.h
@@ -22,18 +22,16 @@
#define TIME_METHOD() MethodTimer __method_timer(__func__)
class MethodTimer {
public:
- explicit MethodTimer(const char* name)
- : mMethodName(name) {
- gettimeofday(&mStart, nullptr);
- }
+ explicit MethodTimer(const char* name) : mMethodName(name) { gettimeofday(&mStart, nullptr); }
~MethodTimer() {
struct timeval stop;
gettimeofday(&stop, nullptr);
- long long elapsed = (stop.tv_sec * 1000000) - (mStart.tv_sec * 1000000)
- + (stop.tv_usec - mStart.tv_usec);
+ long long elapsed = (stop.tv_sec * 1000000) - (mStart.tv_sec * 1000000) +
+ (stop.tv_usec - mStart.tv_usec);
ALOGD("%s took %.2fms", mMethodName, elapsed / 1000.0);
}
+
private:
const char* mMethodName;
struct timeval mStart;
diff --git a/libs/hwui/utils/TraceUtils.h b/libs/hwui/utils/TraceUtils.h
index ddc272c64851..1869d00396c0 100644
--- a/libs/hwui/utils/TraceUtils.h
+++ b/libs/hwui/utils/TraceUtils.h
@@ -18,11 +18,11 @@
#include <utils/Trace.h>
-#define ATRACE_FORMAT(fmt, ...) \
- TraceUtils::TraceEnder __traceEnder = (TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__), TraceUtils::TraceEnder())
+#define ATRACE_FORMAT(fmt, ...) \
+ TraceUtils::TraceEnder __traceEnder = \
+ (TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__), TraceUtils::TraceEnder())
-#define ATRACE_FORMAT_BEGIN(fmt, ...) \
- TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__)
+#define ATRACE_FORMAT_BEGIN(fmt, ...) TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__)
namespace android {
namespace uirenderer {
@@ -48,7 +48,7 @@ public:
ATRACE_BEGIN(buf);
}
-}; // class TraceUtils
+}; // class TraceUtils
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/utils/VectorDrawableUtils.cpp b/libs/hwui/utils/VectorDrawableUtils.cpp
index 6f0c96db4b1e..6b8f3154dd36 100644
--- a/libs/hwui/utils/VectorDrawableUtils.cpp
+++ b/libs/hwui/utils/VectorDrawableUtils.cpp
@@ -32,8 +32,8 @@ public:
float ctrlPointY = 0;
float currentSegmentStartX = 0;
float currentSegmentStartY = 0;
- void addCommand(SkPath* outPath, char previousCmd,
- char cmd, const std::vector<float>* points, size_t start, size_t end);
+ void addCommand(SkPath* outPath, char previousCmd, char cmd, const std::vector<float>* points,
+ size_t start, size_t end);
};
bool VectorDrawableUtils::canMorph(const PathData& morphFrom, const PathData& morphTo) {
@@ -42,8 +42,8 @@ bool VectorDrawableUtils::canMorph(const PathData& morphFrom, const PathData& mo
}
for (unsigned int i = 0; i < morphFrom.verbs.size(); i++) {
- if (morphFrom.verbs[i] != morphTo.verbs[i]
- || morphFrom.verbSizes[i] != morphTo.verbSizes[i]) {
+ if (morphFrom.verbs[i] != morphTo.verbs[i] ||
+ morphFrom.verbSizes[i] != morphTo.verbSizes[i]) {
return false;
}
}
@@ -51,7 +51,7 @@ bool VectorDrawableUtils::canMorph(const PathData& morphFrom, const PathData& mo
}
bool VectorDrawableUtils::interpolatePathData(PathData* outData, const PathData& morphFrom,
- const PathData& morphTo, float fraction) {
+ const PathData& morphTo, float fraction) {
if (!canMorph(morphFrom, morphTo)) {
return false;
}
@@ -59,9 +59,9 @@ bool VectorDrawableUtils::interpolatePathData(PathData* outData, const PathData&
return true;
}
- /**
- * Convert an array of PathVerb to Path.
- */
+/**
+* Convert an array of PathVerb to Path.
+*/
void VectorDrawableUtils::verbsToPath(SkPath* outPath, const PathData& data) {
PathResolver resolver;
char previousCommand = 'm';
@@ -70,7 +70,7 @@ void VectorDrawableUtils::verbsToPath(SkPath* outPath, const PathData& data) {
for (unsigned int i = 0; i < data.verbs.size(); i++) {
size_t verbSize = data.verbSizes[i];
resolver.addCommand(outPath, previousCommand, data.verbs[i], &data.points, start,
- start + verbSize);
+ start + verbSize);
previousCommand = data.verbs[i];
start += verbSize;
}
@@ -85,8 +85,8 @@ void VectorDrawableUtils::verbsToPath(SkPath* outPath, const PathData& data) {
* @param nodeTo The end value as a PathVerb
* @param fraction The fraction to interpolate.
*/
-void VectorDrawableUtils::interpolatePaths(PathData* outData,
- const PathData& from, const PathData& to, float fraction) {
+void VectorDrawableUtils::interpolatePaths(PathData* outData, const PathData& from,
+ const PathData& to, float fraction) {
outData->points.resize(from.points.size());
outData->verbSizes = from.verbSizes;
outData->verbs = from.verbs;
@@ -96,396 +96,234 @@ void VectorDrawableUtils::interpolatePaths(PathData* outData,
}
}
-/**
- * Converts an arc to cubic Bezier segments and records them in p.
- *
- * @param p The target for the cubic Bezier segments
- * @param cx The x coordinate center of the ellipse
- * @param cy The y coordinate center of the ellipse
- * @param a The radius of the ellipse in the horizontal direction
- * @param b The radius of the ellipse in the vertical direction
- * @param e1x E(eta1) x coordinate of the starting point of the arc
- * @param e1y E(eta2) y coordinate of the starting point of the arc
- * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
- * @param start The start angle of the arc on the ellipse
- * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
- */
-static void arcToBezier(SkPath* p,
- double cx,
- double cy,
- double a,
- double b,
- double e1x,
- double e1y,
- double theta,
- double start,
- double sweep) {
- // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
- // and http://www.spaceroots.org/documents/ellipse/node22.html
-
- // Maximum of 45 degrees per cubic Bezier segment
- int numSegments = ceil(fabs(sweep * 4 / M_PI));
-
- double eta1 = start;
- double cosTheta = cos(theta);
- double sinTheta = sin(theta);
- double cosEta1 = cos(eta1);
- double sinEta1 = sin(eta1);
- double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
- double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
-
- double anglePerSegment = sweep / numSegments;
- for (int i = 0; i < numSegments; i++) {
- double eta2 = eta1 + anglePerSegment;
- double sinEta2 = sin(eta2);
- double cosEta2 = cos(eta2);
- double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
- double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
- double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
- double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
- double tanDiff2 = tan((eta2 - eta1) / 2);
- double alpha =
- sin(eta2 - eta1) * (sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
- double q1x = e1x + alpha * ep1x;
- double q1y = e1y + alpha * ep1y;
- double q2x = e2x - alpha * ep2x;
- double q2y = e2y - alpha * ep2y;
-
- p->cubicTo((float) q1x,
- (float) q1y,
- (float) q2x,
- (float) q2y,
- (float) e2x,
- (float) e2y);
- eta1 = eta2;
- e1x = e2x;
- e1y = e2y;
- ep1x = ep2x;
- ep1y = ep2y;
- }
-}
-
-inline double toRadians(float theta) { return theta * M_PI / 180;}
-
-static void drawArc(SkPath* p,
- float x0,
- float y0,
- float x1,
- float y1,
- float a,
- float b,
- float theta,
- bool isMoreThanHalf,
- bool isPositiveArc) {
-
- /* Convert rotation angle from degrees to radians */
- double thetaD = toRadians(theta);
- /* Pre-compute rotation matrix entries */
- double cosTheta = cos(thetaD);
- double sinTheta = sin(thetaD);
- /* Transform (x0, y0) and (x1, y1) into unit space */
- /* using (inverse) rotation, followed by (inverse) scale */
- double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
- double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
- double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
- double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
-
- /* Compute differences and averages */
- double dx = x0p - x1p;
- double dy = y0p - y1p;
- double xm = (x0p + x1p) / 2;
- double ym = (y0p + y1p) / 2;
- /* Solve for intersecting unit circles */
- double dsq = dx * dx + dy * dy;
- if (dsq == 0.0) {
- VECTOR_DRAWABLE_LOGD("Points are coincident");
- return; /* Points are coincident */
- }
- double disc = 1.0 / dsq - 1.0 / 4.0;
- if (disc < 0.0) {
- VECTOR_DRAWABLE_LOGD("Points are too far apart %f", dsq);
- float adjust = (float) (sqrt(dsq) / 1.99999);
- drawArc(p, x0, y0, x1, y1, a * adjust,
- b * adjust, theta, isMoreThanHalf, isPositiveArc);
- return; /* Points are too far apart */
- }
- double s = sqrt(disc);
- double sdx = s * dx;
- double sdy = s * dy;
- double cx;
- double cy;
- if (isMoreThanHalf == isPositiveArc) {
- cx = xm - sdy;
- cy = ym + sdx;
- } else {
- cx = xm + sdy;
- cy = ym - sdx;
- }
-
- double eta0 = atan2((y0p - cy), (x0p - cx));
-
- double eta1 = atan2((y1p - cy), (x1p - cx));
-
- double sweep = (eta1 - eta0);
- if (isPositiveArc != (sweep >= 0)) {
- if (sweep > 0) {
- sweep -= 2 * M_PI;
- } else {
- sweep += 2 * M_PI;
- }
- }
-
- cx *= a;
- cy *= b;
- double tcx = cx;
- cx = cx * cosTheta - cy * sinTheta;
- cy = tcx * sinTheta + cy * cosTheta;
-
- arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
-}
-
-
-
// Use the given verb, and points in the range [start, end) to insert a command into the SkPath.
-void PathResolver::addCommand(SkPath* outPath, char previousCmd,
- char cmd, const std::vector<float>* points, size_t start, size_t end) {
-
+void PathResolver::addCommand(SkPath* outPath, char previousCmd, char cmd,
+ const std::vector<float>* points, size_t start, size_t end) {
int incr = 2;
float reflectiveCtrlPointX;
float reflectiveCtrlPointY;
switch (cmd) {
- case 'z':
- case 'Z':
- outPath->close();
- // Path is closed here, but we need to move the pen to the
- // closed position. So we cache the segment's starting position,
- // and restore it here.
- currentX = currentSegmentStartX;
- currentY = currentSegmentStartY;
- ctrlPointX = currentSegmentStartX;
- ctrlPointY = currentSegmentStartY;
- outPath->moveTo(currentX, currentY);
- break;
- case 'm':
- case 'M':
- case 'l':
- case 'L':
- case 't':
- case 'T':
- incr = 2;
- break;
- case 'h':
- case 'H':
- case 'v':
- case 'V':
- incr = 1;
- break;
- case 'c':
- case 'C':
- incr = 6;
- break;
- case 's':
- case 'S':
- case 'q':
- case 'Q':
- incr = 4;
- break;
- case 'a':
- case 'A':
- incr = 7;
- break;
- }
-
- for (unsigned int k = start; k < end; k += incr) {
- switch (cmd) {
- case 'm': // moveto - Start a new sub-path (relative)
- currentX += points->at(k + 0);
- currentY += points->at(k + 1);
- if (k > start) {
- // According to the spec, if a moveto is followed by multiple
- // pairs of coordinates, the subsequent pairs are treated as
- // implicit lineto commands.
- outPath->rLineTo(points->at(k + 0), points->at(k + 1));
- } else {
- outPath->rMoveTo(points->at(k + 0), points->at(k + 1));
- currentSegmentStartX = currentX;
- currentSegmentStartY = currentY;
- }
+ case 'z':
+ case 'Z':
+ outPath->close();
+ // Path is closed here, but we need to move the pen to the
+ // closed position. So we cache the segment's starting position,
+ // and restore it here.
+ currentX = currentSegmentStartX;
+ currentY = currentSegmentStartY;
+ ctrlPointX = currentSegmentStartX;
+ ctrlPointY = currentSegmentStartY;
+ outPath->moveTo(currentX, currentY);
break;
- case 'M': // moveto - Start a new sub-path
- currentX = points->at(k + 0);
- currentY = points->at(k + 1);
- if (k > start) {
- // According to the spec, if a moveto is followed by multiple
- // pairs of coordinates, the subsequent pairs are treated as
- // implicit lineto commands.
- outPath->lineTo(points->at(k + 0), points->at(k + 1));
- } else {
- outPath->moveTo(points->at(k + 0), points->at(k + 1));
- currentSegmentStartX = currentX;
- currentSegmentStartY = currentY;
- }
- break;
- case 'l': // lineto - Draw a line from the current point (relative)
- outPath->rLineTo(points->at(k + 0), points->at(k + 1));
- currentX += points->at(k + 0);
- currentY += points->at(k + 1);
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ incr = 2;
break;
- case 'L': // lineto - Draw a line from the current point
- outPath->lineTo(points->at(k + 0), points->at(k + 1));
- currentX = points->at(k + 0);
- currentY = points->at(k + 1);
+ case 'h':
+ case 'H':
+ case 'v':
+ case 'V':
+ incr = 1;
break;
- case 'h': // horizontal lineto - Draws a horizontal line (relative)
- outPath->rLineTo(points->at(k + 0), 0);
- currentX += points->at(k + 0);
+ case 'c':
+ case 'C':
+ incr = 6;
break;
- case 'H': // horizontal lineto - Draws a horizontal line
- outPath->lineTo(points->at(k + 0), currentY);
- currentX = points->at(k + 0);
+ case 's':
+ case 'S':
+ case 'q':
+ case 'Q':
+ incr = 4;
break;
- case 'v': // vertical lineto - Draws a vertical line from the current point (r)
- outPath->rLineTo(0, points->at(k + 0));
- currentY += points->at(k + 0);
+ case 'a':
+ case 'A':
+ incr = 7;
break;
- case 'V': // vertical lineto - Draws a vertical line from the current point
- outPath->lineTo(currentX, points->at(k + 0));
- currentY = points->at(k + 0);
- break;
- case 'c': // curveto - Draws a cubic Bézier curve (relative)
- outPath->rCubicTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3),
- points->at(k + 4), points->at(k + 5));
-
- ctrlPointX = currentX + points->at(k + 2);
- ctrlPointY = currentY + points->at(k + 3);
- currentX += points->at(k + 4);
- currentY += points->at(k + 5);
+ }
- break;
- case 'C': // curveto - Draws a cubic Bézier curve
- outPath->cubicTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3),
- points->at(k + 4), points->at(k + 5));
- currentX = points->at(k + 4);
- currentY = points->at(k + 5);
- ctrlPointX = points->at(k + 2);
- ctrlPointY = points->at(k + 3);
- break;
- case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
- reflectiveCtrlPointX = 0;
- reflectiveCtrlPointY = 0;
- if (previousCmd == 'c' || previousCmd == 's'
- || previousCmd == 'C' || previousCmd == 'S') {
- reflectiveCtrlPointX = currentX - ctrlPointX;
- reflectiveCtrlPointY = currentY - ctrlPointY;
- }
- outPath->rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- points->at(k + 0), points->at(k + 1),
- points->at(k + 2), points->at(k + 3));
- ctrlPointX = currentX + points->at(k + 0);
- ctrlPointY = currentY + points->at(k + 1);
- currentX += points->at(k + 2);
- currentY += points->at(k + 3);
- break;
- case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
- reflectiveCtrlPointX = currentX;
- reflectiveCtrlPointY = currentY;
- if (previousCmd == 'c' || previousCmd == 's'
- || previousCmd == 'C' || previousCmd == 'S') {
- reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
- reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
- }
- outPath->cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3));
- ctrlPointX = points->at(k + 0);
- ctrlPointY = points->at(k + 1);
- currentX = points->at(k + 2);
- currentY = points->at(k + 3);
- break;
- case 'q': // Draws a quadratic Bézier (relative)
- outPath->rQuadTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3));
- ctrlPointX = currentX + points->at(k + 0);
- ctrlPointY = currentY + points->at(k + 1);
- currentX += points->at(k + 2);
- currentY += points->at(k + 3);
- break;
- case 'Q': // Draws a quadratic Bézier
- outPath->quadTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3));
- ctrlPointX = points->at(k + 0);
- ctrlPointY = points->at(k + 1);
- currentX = points->at(k + 2);
- currentY = points->at(k + 3);
- break;
- case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
- reflectiveCtrlPointX = 0;
- reflectiveCtrlPointY = 0;
- if (previousCmd == 'q' || previousCmd == 't'
- || previousCmd == 'Q' || previousCmd == 'T') {
- reflectiveCtrlPointX = currentX - ctrlPointX;
- reflectiveCtrlPointY = currentY - ctrlPointY;
- }
- outPath->rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- points->at(k + 0), points->at(k + 1));
- ctrlPointX = currentX + reflectiveCtrlPointX;
- ctrlPointY = currentY + reflectiveCtrlPointY;
- currentX += points->at(k + 0);
- currentY += points->at(k + 1);
- break;
- case 'T': // Draws a quadratic Bézier curve (reflective control point)
- reflectiveCtrlPointX = currentX;
- reflectiveCtrlPointY = currentY;
- if (previousCmd == 'q' || previousCmd == 't'
- || previousCmd == 'Q' || previousCmd == 'T') {
- reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
- reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
- }
- outPath->quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- points->at(k + 0), points->at(k + 1));
- ctrlPointX = reflectiveCtrlPointX;
- ctrlPointY = reflectiveCtrlPointY;
- currentX = points->at(k + 0);
- currentY = points->at(k + 1);
- break;
- case 'a': // Draws an elliptical arc
- // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
- drawArc(outPath,
- currentX,
- currentY,
- points->at(k + 5) + currentX,
- points->at(k + 6) + currentY,
- points->at(k + 0),
- points->at(k + 1),
- points->at(k + 2),
- points->at(k + 3) != 0,
- points->at(k + 4) != 0);
- currentX += points->at(k + 5);
- currentY += points->at(k + 6);
- ctrlPointX = currentX;
- ctrlPointY = currentY;
- break;
- case 'A': // Draws an elliptical arc
- drawArc(outPath,
- currentX,
- currentY,
- points->at(k + 5),
- points->at(k + 6),
- points->at(k + 0),
- points->at(k + 1),
- points->at(k + 2),
- points->at(k + 3) != 0,
- points->at(k + 4) != 0);
- currentX = points->at(k + 5);
- currentY = points->at(k + 6);
- ctrlPointX = currentX;
- ctrlPointY = currentY;
- break;
- default:
- LOG_ALWAYS_FATAL("Unsupported command: %c", cmd);
- break;
+ for (unsigned int k = start; k < end; k += incr) {
+ switch (cmd) {
+ case 'm': // moveto - Start a new sub-path (relative)
+ currentX += points->at(k + 0);
+ currentY += points->at(k + 1);
+ if (k > start) {
+ // According to the spec, if a moveto is followed by multiple
+ // pairs of coordinates, the subsequent pairs are treated as
+ // implicit lineto commands.
+ outPath->rLineTo(points->at(k + 0), points->at(k + 1));
+ } else {
+ outPath->rMoveTo(points->at(k + 0), points->at(k + 1));
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ }
+ break;
+ case 'M': // moveto - Start a new sub-path
+ currentX = points->at(k + 0);
+ currentY = points->at(k + 1);
+ if (k > start) {
+ // According to the spec, if a moveto is followed by multiple
+ // pairs of coordinates, the subsequent pairs are treated as
+ // implicit lineto commands.
+ outPath->lineTo(points->at(k + 0), points->at(k + 1));
+ } else {
+ outPath->moveTo(points->at(k + 0), points->at(k + 1));
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ }
+ break;
+ case 'l': // lineto - Draw a line from the current point (relative)
+ outPath->rLineTo(points->at(k + 0), points->at(k + 1));
+ currentX += points->at(k + 0);
+ currentY += points->at(k + 1);
+ break;
+ case 'L': // lineto - Draw a line from the current point
+ outPath->lineTo(points->at(k + 0), points->at(k + 1));
+ currentX = points->at(k + 0);
+ currentY = points->at(k + 1);
+ break;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ outPath->rLineTo(points->at(k + 0), 0);
+ currentX += points->at(k + 0);
+ break;
+ case 'H': // horizontal lineto - Draws a horizontal line
+ outPath->lineTo(points->at(k + 0), currentY);
+ currentX = points->at(k + 0);
+ break;
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ outPath->rLineTo(0, points->at(k + 0));
+ currentY += points->at(k + 0);
+ break;
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ outPath->lineTo(currentX, points->at(k + 0));
+ currentY = points->at(k + 0);
+ break;
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ outPath->rCubicTo(points->at(k + 0), points->at(k + 1), points->at(k + 2),
+ points->at(k + 3), points->at(k + 4), points->at(k + 5));
+
+ ctrlPointX = currentX + points->at(k + 2);
+ ctrlPointY = currentY + points->at(k + 3);
+ currentX += points->at(k + 4);
+ currentY += points->at(k + 5);
+
+ break;
+ case 'C': // curveto - Draws a cubic Bézier curve
+ outPath->cubicTo(points->at(k + 0), points->at(k + 1), points->at(k + 2),
+ points->at(k + 3), points->at(k + 4), points->at(k + 5));
+ currentX = points->at(k + 4);
+ currentY = points->at(k + 5);
+ ctrlPointX = points->at(k + 2);
+ ctrlPointY = points->at(k + 3);
+ break;
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'c' || previousCmd == 's' || previousCmd == 'C' ||
+ previousCmd == 'S') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ outPath->rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, points->at(k + 0),
+ points->at(k + 1), points->at(k + 2), points->at(k + 3));
+ ctrlPointX = currentX + points->at(k + 0);
+ ctrlPointY = currentY + points->at(k + 1);
+ currentX += points->at(k + 2);
+ currentY += points->at(k + 3);
+ break;
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'c' || previousCmd == 's' || previousCmd == 'C' ||
+ previousCmd == 'S') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ outPath->cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, points->at(k + 0),
+ points->at(k + 1), points->at(k + 2), points->at(k + 3));
+ ctrlPointX = points->at(k + 0);
+ ctrlPointY = points->at(k + 1);
+ currentX = points->at(k + 2);
+ currentY = points->at(k + 3);
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ outPath->rQuadTo(points->at(k + 0), points->at(k + 1), points->at(k + 2),
+ points->at(k + 3));
+ ctrlPointX = currentX + points->at(k + 0);
+ ctrlPointY = currentY + points->at(k + 1);
+ currentX += points->at(k + 2);
+ currentY += points->at(k + 3);
+ break;
+ case 'Q': // Draws a quadratic Bézier
+ outPath->quadTo(points->at(k + 0), points->at(k + 1), points->at(k + 2),
+ points->at(k + 3));
+ ctrlPointX = points->at(k + 0);
+ ctrlPointY = points->at(k + 1);
+ currentX = points->at(k + 2);
+ currentY = points->at(k + 3);
+ break;
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'q' || previousCmd == 't' || previousCmd == 'Q' ||
+ previousCmd == 'T') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ outPath->rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, points->at(k + 0),
+ points->at(k + 1));
+ ctrlPointX = currentX + reflectiveCtrlPointX;
+ ctrlPointY = currentY + reflectiveCtrlPointY;
+ currentX += points->at(k + 0);
+ currentY += points->at(k + 1);
+ break;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'q' || previousCmd == 't' || previousCmd == 'Q' ||
+ previousCmd == 'T') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ outPath->quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, points->at(k + 0),
+ points->at(k + 1));
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
+ currentX = points->at(k + 0);
+ currentY = points->at(k + 1);
+ break;
+ case 'a': // Draws an elliptical arc
+ // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+ outPath->arcTo(points->at(k + 0), points->at(k + 1), points->at(k + 2),
+ (SkPath::ArcSize) (points->at(k + 3) != 0),
+ (SkPath::Direction) (points->at(k + 4) == 0),
+ points->at(k + 5) + currentX, points->at(k + 6) + currentY);
+ currentX += points->at(k + 5);
+ currentY += points->at(k + 6);
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ case 'A': // Draws an elliptical arc
+ outPath->arcTo(points->at(k + 0), points->at(k + 1), points->at(k + 2),
+ (SkPath::ArcSize) (points->at(k + 3) != 0),
+ (SkPath::Direction) (points->at(k + 4) == 0),
+ points->at(k + 5), points->at(k + 6));
+ currentX = points->at(k + 5);
+ currentY = points->at(k + 6);
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unsupported command: %c", cmd);
+ break;
}
previousCmd = cmd;
}
}
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/utils/VectorDrawableUtils.h b/libs/hwui/utils/VectorDrawableUtils.h
index b5ef5102d219..4be48fb942fc 100644
--- a/libs/hwui/utils/VectorDrawableUtils.h
+++ b/libs/hwui/utils/VectorDrawableUtils.h
@@ -20,8 +20,8 @@
#include "VectorDrawable.h"
#include <cutils/compiler.h>
-#include "SkPath.h"
#include <vector>
+#include "SkPath.h"
namespace android {
namespace uirenderer {
@@ -30,11 +30,11 @@ class VectorDrawableUtils {
public:
ANDROID_API static bool canMorph(const PathData& morphFrom, const PathData& morphTo);
ANDROID_API static bool interpolatePathData(PathData* outData, const PathData& morphFrom,
- const PathData& morphTo, float fraction);
+ const PathData& morphTo, float fraction);
ANDROID_API static void verbsToPath(SkPath* outPath, const PathData& data);
static void interpolatePaths(PathData* outPathData, const PathData& from, const PathData& to,
- float fraction);
+ float fraction);
};
-} // namespace uirenderer
-} // namespace android
+} // namespace uirenderer
+} // namespace android
#endif /* ANDROID_HWUI_VECTORDRAWABLE_UTILS_H*/